What is the difference between a Deployment and a StatefulSet?
Updated Feb 20, 2026
Short answer
A Deployment manages interchangeable, stateless pods with random names, replacing them in any order. A StatefulSet gives each pod a stable ordinal identity, a stable network hostname, and its own persistent volume that survives rescheduling — and it creates, updates, and deletes them in strict order. Use a Deployment unless a pod's identity or storage genuinely matters.
Deep explanation
| Deployment | StatefulSet | |
|---|---|---|
| Pod names | web-7d4f-x9k2 random | db-0, db-1, db-2 ordinal |
| Identity across restarts | none | stable |
| Storage | shared or ephemeral | one PVC per pod, retained |
| Scaling / update order | parallel, arbitrary | sequential, ordered |
| DNS | one service VIP | per-pod stable hostname |
| Scale to zero and back | pods are new | same identity and volume |
Stable identity is the whole point. db-0 is always db-0. When it is rescheduled onto another node it keeps its name, its DNS entry db-0.db-headless.default.svc.cluster.local, and — crucially — reattaches the same PersistentVolumeClaim. That is what makes clustered databases work: a replica must find its own data, and peers must be able to address a specific member.
Ordered operations matter for consensus systems. Scaling up creates db-0, waits for it to be Ready, then db-1. Scaling down removes the highest ordinal first. A three-node etcd or ZooKeeper cluster depends on this — starting all three simultaneously, or removing an arbitrary member, can break quorum.
apiVersion: apps/v1kind: StatefulSetmetadata: { name: db }spec: serviceName: db-headless # REQUIRED for per-pod DNS replicas: 3 volumeClaimTemplates: # each pod gets its OWN PVC - metadata: { name: data } spec: accessModes: [ReadWriteOnce] resources: { requests: { storage: 100Gi } }volumeClaimTemplates is what a Deployment cannot express — it generates data-db-0, data-db-1, data-db-2, each bound to its pod.
The costs are real. Sequential rollouts are slower. A stuck pod blocks the whole rollout. PVCs are not deleted when you delete the StatefulSet — deliberate, to avoid destroying data, but it means orphaned volumes accumulate unnoticed. And running a database on Kubernetes needs an operator for backups, failover, and version upgrades; a StatefulSet alone gives you identity and storage, not database administration.
The common error is reaching for a StatefulSet because an app "has state". If that state lives in an external database or object store, the pods are still interchangeable and a Deployment is correct.
Real-world example
A three-node PostgreSQL cluster:
db-0 -> PVC data-db-0 -> primarydb-1 -> PVC data-db-1 -> replica, streams from db-0.db-headlessdb-2 -> PVC data-db-2 -> replica, streams from db-0.db-headlessWhen db-1's node fails, it is rescheduled elsewhere, keeps the name db-1, reattaches data-db-1, and resumes replication from where it stopped. Under a Deployment the replacement pod would get a new random name and either an empty volume or one shared with others — a fresh replica needing a full base backup every time a node is drained.
By contrast, the stateless API in front of that database belongs in a Deployment: any pod serves any request, and rolling ten of them in parallel is exactly what you want.
Common mistakes
- - Using a StatefulSet because the application 'has state' when that state lives in an external database — the pods are still interchangeable.
- - Omitting the headless service, without which per-pod DNS names never resolve.
- - Expecting PVCs to be cleaned up on delete
- they are retained deliberately and accumulate as orphans.
- - Assuming a StatefulSet makes a database production-ready — it provides identity and storage, not backup, failover, or upgrades.
- - Being surprised by slow rollouts, since pods update one at a time and a single unready pod stalls the whole thing.
- - Using ReadWriteOnce volumes and then expecting several pods to share them
- that access mode binds to one node.
Follow-up questions
- Why does a StatefulSet need a headless service?
- What happens to PersistentVolumeClaims when a StatefulSet is deleted?
- How does scaling down a StatefulSet differ from a Deployment?
- When would you use a DaemonSet instead of either?