What does a registry's tag-immutability rule prevent, and why does it break a promote-by-retag flow?
answer
- existing mappings freeze, new tags still allowed
- environment tags are pointers by design
- delete-then-push is a loophole
- promotion needs a new name, not a move
- says nothing about image quality
basics
~20 sTag immutability refuses to re-aim an existing tag at different bytes, closing the overwrite path for everyone with push rights. It breaks promotion flows because those flows work by moving a shared staging or prod tag onto each new build.
solid answer
~50 sImmutability is a registry-side rule: once a tag maps to a digest, a push that would remap it is rejected. That removes the silent-overwrite path - including from a neighbouring team that happens to share push rights to the repository. It is narrower than people assume: brand-new tags can still be pushed, the rule normally applies going forward and per repository or tag pattern, it says nothing about whether the image is any good, and if tag deletion is still permitted then delete-then-push reproduces the overwrite with one extra step. It also collides head-on with promotion by retagging, because a `:staging` or `:prod` tag is by design a pointer that moves. The resolution is to promote by copying the same manifest under a new unique release tag, record its digest, and let the environment pointer live in git-managed deployment config rather than in the registry.
go deeper
Know that a registry can be configured to refuse re-aiming a tag that already exists, and that this is what stops someone quietly overwriting a release name.
Explain the exact scope: existing mappings freeze, new tags stay pushable, deletion can undo it, and copies into other registries are outside the rule. Then explain why a moving environment tag conflicts with it.
Show how you would roll it out on a live registry without breaking releases: unique immutable build tags, promotion by copying the manifest, deployments referencing digests, and deletion rights restricted and alerted.
Frame it as where release state belongs - a mutable registry pointer that anyone with push access can rewrite, or a reviewed file in your source of truth - and argue the cost of the migration against that.
## What the rule actually does Tag immutability is enforcement inside the registry: for a repository (or a tag pattern) covered by the rule, a push that would change an existing tag's mapping is refused. The value is that it removes an attack and accident path you otherwise cannot see from the outside. On a shared internal registry, push rights are usually granted per repository or broader, so any team - or any CI job holding a token for that scope - can quietly re-aim `:staging` or `:prod` at bytes of their choosing. Immutability turns that from a silent success into a rejected push, which is both a preventive control and a signal. It also makes a tag *usable as evidence*. If tags cannot move, then "this release was built from this commit and shipped as `release-2026.04.3`" is a durable statement about one artifact rather than about whatever the name means today. ## What it does not do Be precise, because interviewers push on exactly these edges: - **New tags are still free.** Immutability freezes existing mappings; it does not restrict who may push a new name. An attacker who can push can still publish `release-2026.04.4` and hope somebody deploys it. - **It is scoped.** The rule lives on one registry, usually per repository or tag pattern, and typically applies from the moment it is enabled - it does not retroactively certify what happened before. - **Deletion can undo it.** If the same principals may delete tags, delete-then-push is an overwrite in two moves. An immutability policy without a matching restriction on deletion, plus alerting on tag deletions, is weaker than it looks. - **Copies escape it.** A manifest copied into a mirror, another registry, an air-gapped transfer or a restored backup lands under whatever rules apply *there*. - **It is not a quality claim.** An immutable tag says the name still points where it did. It says nothing about whether the image was reviewed, tested or built from the source you think. Because of that scoping, immutability narrows the window but does not replace referencing images by digest. A digest is verified by the client on every pull, wherever the bytes came from; immutability is a promise made by one server about one namespace. ## Why promotion breaks A very common release design moves builds through environments by retagging: the same image gets `:staging`, and when it passes, the `:prod` tag is moved onto it. "Which build is in prod" is answered by asking the registry what `:prod` means. That is exactly the mutable pointer immutability exists to forbid, so switching the rule on breaks the pipeline on its next promotion. This is not a tooling annoyance; it exposes a design decision that was implicit. Promote-by-retag stores release state in the registry, in a field that is mutable by everyone with push access and has no review, no history you control and no diff. Promote-by-digest stores release state in your source of truth. ## The shape that works 1. **Build once, name it immutably.** Every build gets a unique, never-reused tag (a version plus build identifier), and its digest is recorded at publish time. 2. **Promote by copying, not by moving.** Pushing the same manifest into a production repository - or simply granting it another unique release tag - keeps the digest identical, which is what makes it provably the same artifact. 3. **Deploy by digest.** The deployment configuration in git names the digest. "What is in prod" is then answered by reading a reviewed file, not by querying a mutable pointer. 4. **Keep a human-friendly tag if you like**, but make it decoration: nothing in the deployment path may resolve it. ## The migration cost Enabling immutability on a live registry is a small project, not a checkbox. Existing environment tags must be retired or excluded, retry logic that reruns a publish step will now fail on the second attempt (which is arguably correct, but it will page someone), and any tooling that answers questions by reading tags needs to read digests instead. Expect to run the rule on new repositories first, then convert the promotion flow, then enable it on the old ones - and to pair it with a restriction on tag deletion, or you have simply added a step to the overwrite.
- If tag deletion is still permitted, is the tag really immutable?Not meaningfully. Delete-then-recreate reproduces the overwrite with one extra step, so immutability is only as strong as the delete policy around it. Restrict deletion to a small set of identities, alert on every tag deletion, and treat a deletion in a release repository as an incident until proven routine.
- Does immutability remove the need to reference images by digest?No. The guarantee is scoped to one registry and one policy, and a mirror, a restore, a migration or an admin exception all sit outside it. A digest is verified by the client on every pull, so it holds wherever the bytes came from. Use immutability as defence in depth beneath digest references.
- How do you promote across environments once tags cannot move?Copy the same manifest under a new unique release tag, or into the production repository, so the digest is unchanged and provably the same artifact. Then let the deployment config in git name that digest. The environment pointer becomes a reviewed file change rather than a registry write.
saying these in an interview costs you the question
- Thinks immutability applies retroactively to old tags
- Assumes an immutable tag means a verified image
- Forgets delete rights can undo immutability
- Believes it protects copies in mirrors or other registries
- Says promotion requires rebuilding the image