Most Kubernetes workloads fall into one of two categories: The first is stateless, which means apps that don’t need to store data persistently. The second, stateful, includes applications that do retain data on a permanent basis.

Diagram comparing Kubernetes Deployment and StatefulSet. Deployment shows pods with random identifiers, while StatefulSet illustrates pods with persistent identities and attached SSD storage.

Accordingly, Kubernetes offers two fundamentally distinct ways for deploying and managing containerized applications: Deployments and StatefulSets. While each approach is a viable way to run an application, understanding the differences, and what they mean for the way your workloads operate, is critical for choosing the right way to run apps in Kubernetes.

For details, keep reading as we explain everything you could ever want to know about StatefulSet vs. Deployment in Kubernetes, including their main similarities and differences, examples of each type of resource, and guidance on what to use when.

What is a Kubernetes StatefulSet?

A Kubernetes StatefulSet is a group of pods that retain unique, persistent identities, even if they stop and restart. Kubernetes developers use the term “sticky” to refer to pods in a StatefulSet because their identities “stick.”

As the term implies, the purpose of StatefulSets is to run stateful applications – meaning ones that require the ability to maintain a persistent state across stop/restart events. StatefulSets enable this because when pods have a unique, persistent identity, you can associate them persistently with storage resources that house the applications’ state.

Key features of StatefulSets

The defining features of StatefulSets include:

  • Unique, predictable identifiers for each pod in a group of identical pods. The identifiers are created in the format statefulsetname-number, where number is an integer that is incremented for each pod. Thus, your first pod might be named statefulset-example-1, the second would be statefulset-example-2, and so on.
  • The ability to retain and reuse the pod identifiers if the pods shut down and restart.

These are the characteristics that make StatefulSets different from other types of Kubernetes objects, including Deployments (which we’ll discuss in a bit).

When to use StatefulSets

There are three common use cases for StatefulSets:

  1. Workloads that need to store data persistently – such as a Web app that needs to read and write data from a database. A StatefulSet enables this use case by making it possible to create a persistent association between pods (which host the Web app) and the database.
  2. Workloads that require a unique network identity. For instance, imagine you want to run two instances of the same app. One is the production app and the other is a backup instance to which you’ll redirect traffic if the primary instance fails. In this case, you’d need a way to identify both the primary instance and the backup instance uniquely on the network. StatefulSets let you do this because each pod would receive stable network identities – so you could use one pod as the primary instance and the other as the backup, and quickly reroute traffic as needed based on each pod’s identifier.
  3. Workloads that need to be “rolled out” in an ordered way. In other words, you need to start one part of the workload before others. This happens most often in situations where one pod runs code or services that another pod depends on. StatefulSets support this use case by allowing you to control the order in which pods start based on their unique identifiers, ensuring that certain pods start before others.

StatefulSet example

To create a StatefulSet, you write YAML code that describes the resource. For example, the following code defines a StatefulSet that creates three replicas of pods to run an NGINX server. It also creates a persistent volume claim for the pods, allowing them to access stateful storage:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: example-statefulset
spec:
  serviceName: "example-service"  # Headless service for stable network identity
  replicas: 3                 	# Number of pod replicas
  selector:
	matchLabels:
  	app: example             	# Label selector
  template:
	metadata:
  	labels:
    	app: example           	# Labels for the pods
	spec:
  	containers:
  	- name: example-container
    	image: nginx:1.25      	# Container image
    	ports:
    	- containerPort: 80    	# Port exposed by the container
    	volumeMounts:
    	- name: data-volume
      	mountPath: /usr/share/nginx/html  # Path inside the container
  volumeClaimTemplates:        	# Define persistent volume claims
  - metadata:
  	name: data-volume
	spec:
  	accessModes: [ "ReadWriteOnce" ]	# Access mode for the volume
  	resources:
    	requests:
      	storage: 1Gi              	# Storage request for the volume

This will result in a StatefulSet with three pods that have unique identities (example-statefulset-0, example-statefulset-1, and example-statefulset-2).

What is a Kubernetes Deployment?

A Kubernetes Deployment is one or more pods that run in Kubernetes without unique, persistent identifiers.

A Deployment is the most common and most basic way to deploy applications in Kubernetes. Creating a Deployment doesn’t require as much information as setting up a StatefulSet, so you’d typically use a Deployment if you just want to run one or more applications in the most straightforward way.

Note, by the way, that we’re referring to Deployments with a capital D because a Deployment is a specific type of API resource in Kubernetes. More generically, the term deployment could refer to running any type of workload in Kubernetes. But when you see a capitalized Deployment, the term refers to a particular mode of deployment.

Key features of a Kubernetes Deployment

The main features of a Kubernetes Deployment include:

  • The ability to define which pod or pods to run.
  • Selection of the container or containers that should be included within your pod.

Deployments don’t include features for assigning unique identities to pods or maintaining a persistent state – which is what makes them different from StatefulSets.

Note that pods in Deployments do receive identifiers, but they are random IDs that Kubernetes automatically assigns, and they don’t persist – so you can’t use the identifiers as a reliable way of identifying pods.

When to use Deployments

You can think of Deployments as the “default” way of deploying workloads in Kubernetes. Unless your workload has specific requirements (like the need for stable network identities), you should use a Deployment to tell Kubernetes how to run it.

Kubernetes Deployment example

Here’s an example of a Deployment. Like the StatefulSet example above, this creates three pods running NGINX (specifically, it creates the three pods by including three pod replicas within the Deployment):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
  labels:
	app: example-app
spec:
  replicas: 3  # Number of desired replicas
  selector:
	matchLabels:
  	app: example-app
  template:
	metadata:
  	labels:
    	app: example-app  # Label to match with the selector
	spec:
  	containers:
  	- name: example-container
    	image: nginx:1.25  # Container image
    	ports:
    	- containerPort: 80  # Exposed port

Unlike the StatefulSet example, however, these pods won’t have unique identifiers. Also, there is no persistent volume claim associated with this Deployment, so there’s no way within the Deployment to link the pods to persistent storage.

Kubernetes StatefulSet vs. Deployment: Key differences

| Differences | Description | |---|---| | Stateful vs. stateless applications | StatefulSets are best if you need to run and manage stateful applications; Use Deployments for stateless applications. | | Rollout and update strategy | StatefulSets make it possible to manage rollouts and updates in a sophisticated way. | | Pod identities | Only StatefulSets support unique pod identities. | | Storage access and management | StatefulSets provide a native way of assigning storage resources to pods. |

StatefulSets and Deployments are similar in that they are both ways to run applications in Kubernetes. They also both include much of the same configuration information, such as names for pods and details about the containerized applications that should run inside pods.

But in other key respects, StatefulSets are quite distinct from Deployments. Here are the main differences.

Stateful applications vs. stateless applications

The biggest difference, arguably, is that StatefulSets support stateful applications, while Deployments are designed for stateless applications.

Technically speaking, there are ways of using a Deployment to run a stateless app if you try really hard. For example, you could include code in your containers that allows them to integrate with persistent storage resources directly, without relying on Kubernetes resources like persistent volumes. But this would be clunky at best. In virtually all use cases involving stateful applications, StatefulSets are the way to go.

Pod identities

Another key difference is that in a StatefulSet, each pod receives a unique identity. This doesn’t happen in a Deployment, even if the Deployment includes multiple replicas.

As we explained above, unique identities are important in situations where you need to associate specific pods with specific persistent storage resources, establish a unique network identity so you can direct traffic to particular pods, or control the order in which pods start.

Rollout and update strategy

By creating pods with unique identifiers, StatefulSets make it easier to control how pods are rolled out because you can start certain pods before others. With a Deployment, Kubernetes attempts to start all pods at the same time.

By a similar token, StatefulSets enable more sophisticated update strategies by allowing you to deploy an updated version of one pod before another. With a Deployment, you don’t have this type of control because again, you have no way of uniquely identifying each pod.

Storage access and management

StatefulSets allow you to assign pods to storage resources and retain those assignments between pod restart events. This is the main way in which StatefulSets support stateful applications. Since Deployments don’t provide a built-in mechanism for assigning pods to storage, they are typically only useful if you’re running stateless applications.

Diagram comparing Kubernetes Deployment and StatefulSet. Deployment pods have random IDs (e.g., mysql-yhx123), while StatefulSet pods have sequential names (e.g., mysql-0) based on ordinal numbers.

Common mistakes to avoid with StatefulSets and Deployments

To use StatefulSets and Deployments effectively, it’s important to avoid common mistakes or antipatterns, including the following.

Misusing StatefulSets for stateless applications

First, don’t use StatefulSets if you only want to run a stateless application.

Technically speaking, there’s nothing stopping you from creating a StatefulSet for a stateless application. To do so, you’d simply define the pod or pods you want to run and the containers to include in them. You don’t have to include a persistent volume claim or other storage resources within the StatefulSet if you don’t want to.

That said, using a StatefulSet in this way unnecessarily complicates your setup. It’s faster and easier to create a Deployment if you do not require persistent storage resources or unique pod identifiers.

Trying to use Deployments for stateful applications

On the other side of the coin, it’s a mistake to attempt to shoehorn a stateful application into a Deployment.

As we mentioned, there are ways of doing this, such as including logic in your containers that tells them how to interact with persistent storage (if that’s your goal) or that creates some type of unique identifier for each container that other services can reference.

But if you opt for this approach, you’re creating a lot of unnecessary work for yourself. You’ll also likely degrade overall application performance because the additional logic inside your apps translates to higher CPU and memory usage. And you create more opportunities for security vulnerabilities to pop up, too.

In short, if you need to run a stateful app, use a StatefulSet. This approach allows you to take advantage of native features within Kubernetes for running stateful applications, which is a simpler, more efficient, and more secure way to do it.

StatefulSet vs. Deployment: How to choose the right option

Although the intricacies of how StatefulSets and Deployments work are a bit complex, deciding which type of resource to use isn’t. It boils down to knowing whether a workload is stateful and/or requires pods with unique identifiers (in which case you should choose a StatefulSet) or not (in which case, use a Deployment).

You might be thinking: “What if my workload isn’t stateful now, but might become stateful in the future? Should I run it as a StatefulSet just in case?” This is a valid question because workloads do evolve over time. For example, you might currently run a simple Web app that doesn’t store any data persistently, but in the future, you may decide to add features (like user identity management) that require persistent storage. In that case, an app that was once stateless would become stateful.

But that wouldn’t mean that the app has to run as a StatefulSet from day one. It’s pretty easy in Kubernetes to take a stateless app that is running as a Deployment and redeploy it as a StatefulSet. Doing so would entail simply deleting the Deployment (which you can do using the kubectl delete deployment command), and then creating a StatefulSet to run the app.

The bottom line: Choosing between StatefulSet vs. Deployment is not that complicated. Unless your app currently needs the features that only a StatefulSet provides, run it as a Deployment. Worry about the future in the future.

StatefulSet and Deployment troubleshooting with groundcover

The groundcover platform won’t tell you whether you should create a StatefulSet or a Deployment. It will, however, help you troubleshoot and optimize the performance of your Kubernetes workloads no matter how you choose to set them up.

groundcover dashboard displaying Kubernetes workloads with metrics like request rate, error percentage, and latency (P95), along with alerts for issues in various ReplicaSets and namespaces.

By continuously monitoring all parts of your cluster using hyper-efficient eBPF instrumentation, groundcover helps you identify problems and get to the root cause quickly.

And, as an observability tool designed from the ground up for cloud-native platforms like Kubernetes, groundcover understands the nuances that distinguish StatefulSets from Deployments, and allows you to track metrics related to resources like infrastructure (which are important for ensuring that StatefulSets don’t create Kubernetes disk pressure problems) as well as more basic, stateless applications.

Sign up for Updates

Keep up with all things cloud-native observability.

We care about data. Check out our privacy policy.

We care about data. Check out our privacy policy.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.