How do StatefulSets handle persistent storage differently from Deployments?
Quick Answer
A Deployment's Pod template, if it references a PersistentVolumeClaim at all, has every replica sharing the same single PVC (or, more commonly, Deployments simply aren't used with per-replica persistent storage at all) — there's no built-in mechanism for giving each replica its own distinct, durable volume. A StatefulSet's `volumeClaimTemplates` automatically creates a distinct PVC for each replica (`data-web-0`, `data-web-1`, ...), and — critically — that specific PVC stays bound to that specific replica's stable identity across restarts and rescheduling, giving each stateful instance its own persistent, individually-tracked storage.
Detailed Answer
Why a Deployment can't give each replica its own volume
A Deployment's Pod template defines exactly one PVC reference (if any), shared identically across every replica it creates — there's no per-replica templating mechanism. In practice, this means a Deployment either has all replicas sharing one single PVC (only viable for storage backends supporting ReadWriteMany — see the access modes question — and only sensible for genuinely shared data, not per-instance data), or, far more commonly, Deployments simply aren't used at all when each replica needs its own distinct persistent data.
volumeClaimTemplates — per-replica PVCs, automatically
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "web-headless"
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: myapp:1.0
volumeMounts:
- name: data
mountPath: /var/lib/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
Instead of one shared PVC, Kubernetes creates a separate PVC for each replica, named by combining the template name and the Pod's ordinal: data-web-0, data-web-1, data-web-2. Each replica's Pod mounts only its own correspondingly-named PVC.
The critical guarantee: identity-to-storage binding survives rescheduling
If web-1's Pod is deleted and recreated — whether due to a crash, a node failure and rescheduling elsewhere, or a rolling update — the replacement Pod, still named web-1, reattaches to the exact same data-web-1 PVC, not a fresh empty volume. This is what makes StatefulSets suitable for databases and other stateful applications: each instance's identity and its data are durably linked together, regardless of which physical node it currently happens to be running on.
What happens when you scale a StatefulSet down, then back up
Scaling a StatefulSet from 3 replicas down to 1 does not delete data-web-1 or data-web-2's PVCs by default — they're retained. Scaling back up to 3 later re-creates web-1 and web-2, and (depending on the StatefulSet's PVC retention policy setting, a more recent addition to the API) they typically reattach to their original, now-still-existing PVCs, meaning previously-removed replicas can come back with their old data intact — a deliberate safety choice, since silently deleting a stateful replica's data just because it was temporarily scaled down would be dangerous default behavior.
Manual cleanup responsibility
Because PVCs created via volumeClaimTemplates are not automatically deleted when the StatefulSet itself is deleted (again, a deliberate safety default — protecting against accidental data loss), cleaning up a StatefulSet's storage after you genuinely want it gone requires explicitly deleting the underlying PVCs yourself (kubectl delete pvc -l app=web) — an easy step to forget, and a common source of "why is this old data/cost still around" surprises after decommissioning a StatefulSet-based application.
The key distinguishing fact to articulate clearly: it's not just that StatefulSets can use persistent storage (Deployments technically can reference PVCs too) — it's that StatefulSets provide per-replica storage that's durably bound to that replica's stable identity, which is precisely the capability a Deployment's architecture has no mechanism to express at all.