Published 2026-09-25 · Reviewed 2026-09-25

What a rollback can and cannot undo

A rollback command returns your code to an earlier revision, not the world around it. A practical way to separate the artifact you can undo from the schema, data and side effects you cannot, and to design a release so the answer is honest.

  • deployment
  • reliability
  • home servers
  • release

The command that feels like an undo

When a release goes wrong, "roll back" is usually the first answer, and it is often the right one. A rollback command is fast, familiar, and reassuring precisely because it sounds complete. It puts the previous version of a program back in front of users. What it does not do is put the world back.

The confusion starts with the word itself, because it covers several different operations. A Kubernetes rollout undo returns a Deployment to an earlier revision. A container platform retags the previous image. A static host republishes the last build. Each of these changes which artifact is running. None of them changes what the previous artifact already did.

A rollback restores an artifact, not an effect

Kubernetes is a useful reference because it is explicit about what a rollout rollback reverts. A Deployment records its history as revisions, and a rollback returns it to an earlier one. The documentation notes that when you roll back to an earlier revision, only the Deployment's Pod template part is rolled back. In other words, the running configuration returns; the data the previous revision produced does not.

That history is also not infinite. The number of old ReplicaSets retained for rollback is controlled by `.spec.revisionHistoryLimit`, which defaults to ten. Once an old ReplicaSet is deleted, the ability to roll back to that revision goes with it, and a limit of zero means a new rollout cannot be undone at all. So "we can always roll back" is a claim about a setting someone may have changed, and about how recently the good revision ran.

Two habits follow. First, capture the rollback target before you need it: record the previous image tag or revision, not just an intention to return to it. Second, practise the command somewhere harmless. `kubectl rollout undo` supports `--dry-run=server`, which lets you confirm which revision the platform would actually choose before anything moves.

The database does not roll back with the code

The deepest asymmetry is state. Code is a file you can replace; data is a fact you have to live with. Modern migration tools make this unusually clear. Prisma ORM, for example, has no `migrate down` command and no down-migration files. Undoing a change means adding another migration to the history that moves the database to the earlier shape. It is closer to `git revert` than to `git reset`.

That reverse migration is an ordinary, forward-applied change, and it can be destructive. The documentation's own example plans a rollback that drops a column, flags it as containing destructive operations that may cause data loss, and notes that applying it deletes what was stored in that column for good. The opposite mismatch is just as real: if the old code is restored while rows written in the new shape remain, the old code may not understand its own database.

Migration tooling is honest about reachability too. A migration run only applies migrations the project already has, and if no migration path leads from the state the database is in to the state you asked for, it fails rather than improvising. That is a feature, and it means a rollback is a plan you prepare rather than a lever you pull.

Making a change that can be undone

If rollback matters, the change has to be designed for it. The established pattern is parallel change, also called expand and contract. Instead of replacing an interface in one step, you first expand it so both the old and new shapes are accepted, then migrate every caller to the new shape, and only then contract by removing the old one. Each phase stays compatible with the version on either side, which is what allows an old and a new revision to run at the same time.

Deployment styles are applications of the same idea. Canary and blue-green releases keep two versions running at once and shift traffic gradually, so the previous version remains a live, warm fallback instead of a rebuild. The pattern earns its keep exactly where it is least convenient: a schema change that a hurried release would otherwise make in one irreversible step.

A reversibility checklist

Before a change goes out, write five lines and answer them honestly.

  • **What state does this change write?** Name the tables, files, queues and external records it touches. Anything it writes sits outside the rollback.
  • **Is the schema change backwards compatible?** If the previous code cannot run against the new schema, a code rollback is not a recovery.
  • **Can the previous artifact still run?** Confirm the retained revision, image tag or build exists, and that the history limit has not pruned it.
  • **What leaves your boundary?** Sent messages, charges, device commands and webhooks cannot be recalled by a deploy. Treat them as permanent.
  • **Has the rollback been exercised?** A platform dry run, or a reverse migration rehearsed against a copy, is the difference between a plan and a hope.

What a rollback still cannot promise

Even a well-prepared rollback has edges. A reverse migration that drops data cannot restore it unless you saved it first. A rollback attempted while the database is part-way through a failed migration is a recovery problem, not a rollback problem. A recipient who already received a message will not un-receive it. And two versions running at once, during a canary or a blue-green shift, both write to shared state, which is a design question rather than a command.

The honest framing is that rollback is one layer of a recovery plan. It answers "which artifact should be running", and it answers that well. It does not answer "what did the last ten minutes do", and no command can.

What we would do next

Take the next change you are about to ship and split it into four layers: artifact, schema, data and side effects. For each, write one sentence saying whether it can be undone and how long the undo remains available. Where an answer is "no", decide now whether that is acceptable, or whether the change should be split into an expand step that is safe to leave in place. Rollback works best for the changes that were designed to survive it.

Sources and limits

This article synthesises the sources below into a practical explanation. It is not a security standard, legal advice, or a guarantee that guidance current at review time still applies — check the review date above against your own situation.

  1. Deployments — Kubernetes. Documents Deployment revision history and rollback: rolling back to an earlier revision reverts only the Pod template part, .spec.revisionHistoryLimit controls how many old ReplicaSets are retained for rollback and defaults to 10, and once a revision's ReplicaSet is deleted that revision can no longer be restored.
  2. kubectl rollout undo — Kubernetes. Documents the rollback command and its flags, including rolling back to a specific revision with --to-revision and previewing the operation server-side with --dry-run=server.
  3. Rollbacks and recovery — Prisma. States that Prisma ORM has no migrate down command and no down-migration files, so undoing a change adds a new forward migration to the history, and warns that a reverse migration such as dropping a column is destructive and deletes the stored data for good.
  4. Applying a migration — Prisma. States that a migration run only ever applies migrations the project already has, and that when no migration path leads from the database's current state to the requested target the run fails with MIGRATION.PATH_UNREACHABLE.
  5. ParallelChange — Martin Fowler. Describes parallel change, also called expand and contract, for implementing backward-incompatible interface changes safely, and frames canary and blue-green deployment as applications of the pattern where old and new versions run side by side.
  • 2026-07-29

    The alert you always ignore

    An alert nobody acts on is not monitoring. It is noise with a notification sound. A practical way to decide which home-server alerts deserve to interrupt you, using precision, recall, detection time and reset time.

  • 2026-09-23

    Before your automation retries, make the action idempotent

    Retries turn a brief failure into a duplicate side effect unless the action can be repeated safely. A practical checklist for stable operation identifiers, precondition checks, outcome records and bounded retries, and an honest account of what it cannot promise.

  • 2026-09-21

    A missing sensor reading is not zero

    Unknown, unavailable and stale sensor values are not measurements. A practical way to keep missing data out of averages, thresholds and automations, and to leave a household with a safe manual path.

Share this article

0 views · 0 share actions

Community comments

Comments are reviewed before publication. Keep discussion constructive: no harassment, hate, threats, doxxing, spam, illegal material, or attempts to evade moderation.

No approved comments yet.

Sign in to join the discussion.