A rollback works almost instantly, never recreating images or re-downloading anything. That’s no accident: a Deployment never edits an existing ReplicaSet when its template changes, it creates a new one and progressively scales the old one to zero, never deleting it. Rollback just reverses that scaling.

What a Deployment actually manages

A Deployment never creates pods directly: it creates and manages ReplicaSets, each responsible for maintaining a given number of pods matching a precise template. A template change (new image, new environment variable) never modifies the existing ReplicaSet: it creates a new one, with the new template, then orchestrates the transition between the two according to the rolling update strategy.

# Every template change creates a new ReplicaSet,
# the old one stays visible, just scaled to zero
kubectl get replicasets -l app=my-app
# my-app-7d9f8c8b4d   0         0         0
# my-app-5f6b9c7d3a   3         3         3

pod-template-hash, the key that ties it all together

Every ReplicaSet gets a pod-template-hash label, computed from its pod template’s exact content: two identical templates produce the same hash, two different templates produce different hashes. This label lets the Deployment instantly recognize whether an existing ReplicaSet already matches the requested template, without comparing field by field on every reconciliation.

metadata:
  labels:
    pod-template-hash: 7d9f8c8b4d

Why old ReplicaSets don’t disappear

Scaling an old ReplicaSet to zero rather than deleting it preserves its exact configuration history, ready to be instantly reactivated. That’s precisely what kubectl rollout undo leverages: the command recreates nothing from scratch, it identifies the previous ReplicaSet (already present, at zero replicas) and simply flips replica counts between the old and new one.

# Rollback is instant because it only readjusts
# replica counts that already exist
kubectl rollout undo deployment/my-app

revisionHistoryLimit: how many old ReplicaSets to keep

Keeping every old ReplicaSet forever would accumulate an unlimited history: revisionHistoryLimit (10 by default) sets how many previous revisions stay available for rollback, the oldest ones beyond that limit getting permanently deleted.

spec:
  revisionHistoryLimit: 10

A value set too low limits how far back a rollback can go (reverting to a version 15 deployments old becomes impossible if the limit is set to 10); a value set too high accumulates inert ReplicaSets that slightly burden the API with no real benefit past a reasonable history.

Takeaway

A Deployment never edits an existing ReplicaSet: it creates a new one on every template change and scales the old one to zero rather than deleting it, a mechanism identifiable via the pod-template-hash label tying each ReplicaSet to its exact template. This architectural choice is precisely what makes a rollback instant: the command only readjusts replica counts between two already-present ReplicaSets, never recreating anything from scratch. revisionHistoryLimit determines how many revisions stay available for that rollback, a setting to tune based on the actually useful history depth, central for any CI/CD industrialization relying on a fast, reliable rollback.