- Level Up Coding
- Posts
- LUC #11: Embracing Simplicity: A Look Into Stateless Design
LUC #11: Embracing Simplicity: A Look Into Stateless Design
Harnessing stateless design to boost efficiency, scalability, and simplicity.
Welcome back, fellow programming enthusiasts! We have another packed edition of Level Up Coding’s newsletter for you.
In today’s issue:
Breaking Down Stateless Design
How microservices communicate (recap)
Programming essentials: Non-primitive data structures (recap)
End-to-end encryption (recap)
Read time: 7 minutes
Breaking Down Stateless Design
Stateless design is a powerful model that has led to the development of simple yet highly scalable and efficient applications.
“State” refers to stored information that systems use to process requests. This information can change over time as users interact with the application or as system events occur.
Before we dive into the specifics of stateless design, let’s take a look at the alternative — stateful applications.
What are Stateful Applications?
With stateful applications, client data such as user ID, session information, configurations, and preferences are stored to help process requests for a given user. Depending on the functionality and requirements of the application, additional data may be saved, such as shopping cart information for an online store or transaction history for a FinTech service.
A stateful design allows applications to provide a personalized experience to their users while removing the need to share data across multiple requests. For this reason, it is a popular approach for applications with user preferences such as streaming services and online games.
The Birth of Stateless Design
As applications grew in complexity and received increasing amounts of traffic, the limitations of stateful design became apparent. Managing and maintaining session data adds significant performance overhead and complexity to a system. This complexity made it difficult for systems to scale horizontally as sharing state across multiple instances becomes a challenge.
The rapid need for scalability and efficiency drove the popularity of stateless design. Instead of having mechanisms for state management, requests contained all the information needed to process it. This allowed systems to handle high levels of requests while adding flexibility to how the system scales, making it more resource efficient.
Use Cases for Stateless Design
Stateless design has risen in popularity due to its alignment with trends in modern computing such as serverless architecture and microservices. One of the key principles behind microservices is that each service is stateless. This allows microservices to scale independently and ensures resource consumption stays efficient. Serverless computing follows the same concept — each function is invoked independently.
Even applications that require session management can benefit from implementing a stateless design in components of their system. For example, most RESTful APIs are stateless where each API call contains all necessary information. Content delivery networks (CDNs) also follow a stateless design so that every request can be fulfilled by any server in the network without needing to sync session data between all servers or query a single session management store.
Disadvantages of Stateless Design
The size of requests can be considerably larger in stateless design. Moreover, sending data across multiple requests can introduce significant inefficiencies that are far greater than the alternative of managing and querying this data from a central storage system.
It is important to note that stateless design should only be implemented for use cases that are truly stateless. Although stateful design has its share of disadvantages, workarounds can add more complexity and fragility.
Final thoughts
Most applications pick a hybrid approach between stateful and stateless design depending on the needs and constraints of each component. The key to a well-designed system is balance. It should be scalable, simple, and fast without sacrificing functionality.
How microservices communicate (recap)
The most commonly used techniques:
gRPC — Protocol buffers are used to define message and service types. The communication channel is bi-directional with flow control.
WebSockets — A full-duplex channel over an open TCP connection.
RESTful APIs — Provide an interface for communication that uses standard HTTP methods, GET, POST, PATCH, and DELETE. It is stateless which means requests must contain all information needed to process it.
GraphQL — A data query and manipulation language. Consolidates APIs to a single API endpoint.
Event-driven — Services respond to changes in state (events). Events are sent through a message broker or message bus.
Service mesh — Adds a network proxy (sidecar) to every service with it’s own granular configurations.
Programming essentials: Non-primitive data structures (recap)
Non-primitive data structures are made up of primitive data types to make up complex structures.
There are three types of non-primitive data structures:
Linear — elements are arranged sequentially and in a specific order. Linear data structures include arrays, lists, stacks, queues, and dequeues.
Hierarchical — represent data in a tree-like shape. Hierarchical data structures include trees and heaps.
Unordered — elements are not arranged in any specific order. Unordered data structures include Hash tables, sets, and graphs.
End-to-end encryption (recap)
𝗘𝗻𝗱-𝘁𝗼-𝗲𝗻𝗱 𝗲𝗻𝗰𝗿𝘆𝗽𝘁𝗶𝗼𝗻 (𝗘𝟮𝗘𝗘) protects your messages and files from being accessed and manipulated by other people other than those you send them to.
Steps involved in the process:
Keys generated
Public key exchange
Encryption (two types: symmetric, asymmetric)
Data transmission
Decryption
End-to-end encryption is only as powerful as the cryptographic algorithms used, and how well they are implemented.
When done right, E2EE boosts the security of digital communications, protecting them from eavesdropping and tampering.
That wraps up this week’s issue of Level Up Coding’s newsletter!
Join us again next week where we’ll explore load balancers and reverse proxies, S.O.L.I.D principles, and edge computing vs cloud computing.