In this article you’ll learn the differences between stateful and stateless applications, as well as when each can be used. You’ll also see how the two models influence the requirements of DevOps implementations.
What Is State?
A service’s “state” is the persistent information which gets recorded during one transaction or event and then recalled during another. One of the simplest examples of state is a database server: it manages stored data that needs to be reliably persisted. A record saved in one session will need to be retrievable by the next one.
State must be carefully managed so it’s usable in the future. External systems shouldn’t need to provide much information to reference a previous event. A simple ID such as a payment transaction number enables the service to restore the rest of the data associated with the activity, such as the payment amount and the shipping address.
What Are Stateless Applications?
Not every application has state. Some systems don’t work with long-lived data or only cache it to improve performance. They’ll still run if previously stored data is lost.
Stateless applications handle each event in isolation. Events have no awareness of each other or the broader context in which the application operates. This quality makes stateless systems easier to reason about. There’s no risk that previous activity is affecting a current operation.
Is My App Stateful or Stateless?
Some applications blur the lines between the stateful and stateless models. The same system could be considered both stateful and stateless, depending on the perspective you approach it from.
Client-side web applications are usually viewed as stateless from the viewpoint of a service operator. They can be hosted by a static web server, independently of any other components. The app may still accumulate state during use, such as settings saved to the user’s device and a history of recent pages. This form of state is not relevant to DevOps teams as it doesn’t affect how the application is deployed.
State With Containers and the Cloud
Modern applications are often deployed to the cloud as containers. Containers are designed to be ephemeral units of functionality that can be replaced without side effects. This means they are predominantly stateless compute components.
Containers can however be used to encapsulate stateful systems. Persistent volumes provide a means of attaching reliable storage that outlives individual container instances. When compared to traditional VMs and bare-metal deployments, the difference comes down to the inherent intentionality of container state management.
Containerizing a stateful system requires you to anticipate where the state occurs and how it’s stored. You can’t naively write to arbitrary filesystem paths because they won’t be mapped to a volume. Without a volume, the data will be lost if the container stops or gets replaced. A period of refactoring could be required to make your application consistently write to a mounted volume path so you need to identify data storage requirements in advance.
How State Affects DevOps
DevOps processes need to be adjusted depending on whether you’re running stateful or stateless services. Stateless deployment models provide much more operating freedom. You can easily launch new containers and scale them across multiple distributed nodes without having to think about persistent state access.
A stateful service requires a more thoughtful management approach. Each application instance needs to be provided with access to the shared state. This can impose restrictions on how you scale. Few Kubernetes distributions allow multiple Nodes to simultaneously mount a volume with write access, for example.
Both kinds of application require proactive monitoring so you’re aware of issues before they occur. This is more important for stateful solutions because you need to stay ahead of storage requirements and identify when container scheduling options are being affected by volume mounts. Stateful deployments will need to be supported by a regular backup strategy too.
State also complicates the DevOps process by making it hard to exactly reproduce environments. It becomes possible for an issue to exist in production while remaining elusive on a developer’s machine. These problems can be tricky to diagnose. You can make them more manageable by providing mechanisms for developers to clone environments so they can reproduce problems in a sandbox.
State always adds complexity and overheads. You need to configure and provide state management solutions such as volumes and databases, making CI pipelines more complicated and harder to maintain. State is unavoidable in most major applications though so trying too hard to keep systems stateless can be an unhelpful diversion. It’s better to use tools and training to seamlessly integrate stateful applications into your DevOps routines, even if it means there’s going to be more work upfront.
Summary
Distinguishing between stateful and stateless applications is important for DevOps success. Viewed from a DevOps perspective, a stateful application will be more complex to deploy and maintain because you need to provide each instance with access to a persistent data store.
Stateless applications are fully decoupled from their environment which typically makes them easier to containerize and scale in the cloud. However truly stateless systems are relatively rare so you’ll usually be combining them with stateful datastores. Refactoring to stateless components where possible, while building tooling to support stateful deployments alongside, is normally the most effective way to balance streamlined DevOps with your system’s functional requirements.