Sep 28, 2024·7 min read

GitLab container registry cleanup rules that keep safe tags

GitLab container registry cleanup rules help you clear old CI images, cut storage waste, and keep the tags you still need for rollback and incident checks.

GitLab container registry cleanup rules that keep safe tags

Why the registry keeps growing

A GitLab registry usually gets bigger in quiet, boring ways. Every branch build, merge request, and commit can push a new image, even when nobody plans to use that image again. CI keeps moving, and the registry keeps everything unless you tell it not to.

That creates a familiar pattern. New tags show up all day. Old tags stay forever. Teams tag images with branch names, short commit hashes, release candidates, test labels, and one-off fixes. A few weeks later, the registry is full of images tied to work that already ended.

Storage grows even when the app barely changes. A small code update still creates a new tag. Base image updates and dependency rebuilds add more layers over time. Each push looks harmless on its own, but hundreds of small pushes turn into a container registry storage problem that keeps getting worse.

A common case is simple: three developers push several times a day, pipelines build images for feature branches, staging, and main, and most of those tags never reach production. They still sit in the registry for months because nobody wants to guess which ones are safe to delete.

That hesitation makes sense. Rollback is stressful. If production breaks, the team wants a known image ready to deploy. If a security issue appears later, they may need an older image to check what code and dependencies were inside it. So fear wins, cleanup gets postponed, and GitLab image retention never gets a real policy.

Most teams are not careless. They are being careful. The problem is that nobody separates "tags we truly need" from "tags CI created and forgot." GitLab container registry cleanup rules solve exactly that problem. They let you expire throwaway images while keeping the tags your rollback plan and incident process still depend on.

Which tags are worth keeping

Start with the tags your systems use right now. If a server, cluster, or customer environment still pulls a tag, keep it. Deleting a live tag saves a little space and can create a much bigger problem when you need to scale, redeploy, or replace a node.

Next come release tags. These are your safety net when a fresh deploy fails at 2 a.m. If v1.14.2 is the last known good release, keep it even if CI has built twenty newer images since then.

Most teams should keep more than one rollback point. A good baseline is the current production tag plus a small set of recent release tags you trust. That gives you room to step back once or twice without rebuilding an old image under pressure.

Some tags matter for reasons beyond deployment. If the team investigates an outage, a breach, or a supply chain issue, the image tied to that event can become evidence. Security work gets much harder when the exact image is gone and everyone has to guess what it contained.

Audit work has the same need. If you promised a customer, regulator, or internal team that you can show what ran in production on a certain date, keep the image tags that prove it. Logs help, but logs plus the actual image tell a cleaner story.

For most teams, the keep list stays short:

  • the tag production runs today
  • a few recent release tags for rollback
  • any tag tied to an incident or security review
  • any tag you may need for an audit

A small startup does not need a huge archive to stay safe. Keeping prod, the last five semantic version releases, and a handful of tags marked for investigation is often enough. If a tag can restore service, explain an incident, or prove what shipped, treat it like a record, not clutter.

Make tag names predictable

Cleanup rules only work when tag names tell the truth. If your team uses names like latest, test, final, and prod2, nobody knows what is safe to remove. CI image cleanup gets much easier when each tag has one clear purpose.

The first split should be between temporary tags and durable tags. Branch builds are temporary. They help review apps, test runs, and short-lived checks. Release tags are different. You may need them again for rollback, support, or an incident review weeks later.

A simple naming pattern usually works well:

  • branch-main-<sha> or branch-login-fix-<sha> for branch builds
  • mr-142-<sha> for merge request testing
  • release-v1.8.2 for immutable releases
  • prod-current for the image production uses now
  • prod-previous for the last known good production image

Release tags should be boring. release-v1.8.2 is much better than stable-new or good-build. When someone gets paged at night, they should know which image to pull without guessing.

Production tags can be stable without being vague. A moving tag like prod-current helps both humans and deployment tools find the live image fast. Pair it with an immutable release tag on the same image so you always know the exact version behind that pointer.

Teams get into trouble when test tags and rollback tags overlap. If qa, stage, or test-ok sometimes points to an experiment and sometimes points to a release candidate, cleanup rules become guesswork. So does rollback.

Pick one rule and stick to it: temporary tags should describe where the build came from, and keepable tags should describe a release or deployment state. That one choice prevents most cleanup mistakes before you save a single rule.

If you manage several apps, keep the same naming pattern across all of them. People make fewer mistakes when every project answers the same question the same way: is this tag temporary, or will we need it later?

How cleanup rules decide what to delete

GitLab container registry cleanup rules work from tag patterns and retention settings. They do not know which images matter to your team unless your tag names make that obvious.

When cleanup runs, GitLab checks each tag against the rules you set. In plain terms, it asks four questions:

  • Does the tag name match the cleanup pattern?
  • Is the tag older than the age limit?
  • Is it outside the small set of recent tags you want to keep?
  • Is it unprotected?

Only tags that pass those checks move toward deletion. That is why naming matters so much. If people push random tags, the rule cannot tell a safe CI leftover from an image you may need next week.

Keeping the newest few matching tags is especially useful for branch, merge request, and commit tags. Those tags grow fast, but teams often still need the most recent ones for testing or debugging.

Protected tags sit outside the normal cleanup path. If your team protects release tags such as v2.4.1, prod, or staging-approved, GitLab leaves them alone. For most teams, that is the right split: temporary CI output can expire, while rollback tags and forensic tags stay available.

Here is where this works well. Suppose developers push images like pr-182-1a2b3c for merge requests, while release images use v1.9.0. A cleanup rule can target the pr- pattern, keep the latest 10 or 20, and expire older ones after a few days.

The trouble starts when naming drifts. If people also push tags like test, temp, final, or joe-fix, the rule stops being reliable. Good cleanup depends on real tag history, not the naming plan buried in an old wiki page.

Before you save anything, look at the tags your team actually uses. If names are messy, fix that first. Cleanup becomes much safer once every short-lived image looks temporary and every rollback tag looks permanent.

Set a rule without risking rollback

Review Your GitLab Setup
Get outside help with tagging, retention, runners, and deployment flow.

Start with the tags you never want GitLab to touch. Most cleanup regrets come from deleting the one image the team needed for a rollback, an audit, or a late-night bug check. Keep your permanent tags short, obvious, and documented.

For many teams, the safe keep list includes versioned releases, tags used in production or staging, hotfix tags that may come back soon, incident tags, and a small number of recent default branch builds.

After that, decide how many branch images people really use. Be honest. Teams often say they want the last twenty images from every branch, but most only ever pull the last two to five. Keeping too many branch builds turns the registry into a warehouse of guesses.

Feature and test tags should expire quickly. If a branch lives for a few days, keep those images for a few days. If your QA cycle is longer, keep them for a week or two. Old feature tags rarely have a second life.

Release, hotfix, and forensic tags need different treatment. Do not rely on age alone for them. A forensic image from six weeks ago can still matter if you are tracing a security issue or proving what ran during an outage. Exclude those patterns clearly so they survive normal cleanup.

Simple rules usually beat clever ones. Protect permanent tags by pattern. Keep a small number of recent branch images. Delete old feature or test tags on a short timer. That covers most real-world use without turning the policy into something nobody trusts.

Imagine one app builds tags like main-451, feature-login-98, v2.3.0, and forensic-2026-04-12. The logic is straightforward. Keep v2.3.0 and anything starting with forensic-. Keep a few recent main images. Let old feature- tags expire after a short period.

Then watch the first cleanup run closely. Compare what stayed with what disappeared. If the result feels too aggressive, adjust the keep patterns before the next run. One careful review at the start can save hours of rollback pain later.

One simple setup that works

Picture a single app with a normal release flow. Every push to a feature branch creates an image like feat-login-4821. Merges to main create tags such as main-20260413-1030, and releases use clear version tags like v2.7.0.

For that team, a sensible default is easy to define. Keep the 10 newest images from main so you can roll back fast if the latest deploy breaks checkout or login. Ten is usually enough to cover several deploys plus a bad hotfix without filling the registry with months of old build output.

Release tags follow a different rule. If a release is tagged v2.7.0 or v2.7.1, keep it. Those tags mark real shipping points, and teams often need them later for customer support, audits, or incident work.

Feature branch images can age out quickly. Most branches either merge or die, so deleting those images after 7 days is a reasonable starting point. That gives developers enough time to test a branch, reopen a merge request, or compare builds, but it stops stale tags from piling up.

You can also reserve one prefix for incident work, such as incident-492-db-timeout. Those images should stay until the review is over, even if they are older than a week. During an outage, the exact image used in the fix can matter as much as the logs.

A practical rule set for that app looks like this:

  • Keep all release tags such as v1.4.3
  • Keep the 10 most recent tags that start with main-
  • Delete tags that start with feat- after 7 days
  • Keep tags that start with incident- until someone removes them manually

This is why rollback tags work best when names tell a clear story. If every temporary build gets a predictable prefix, GitLab can remove old images without touching the ones tied to rollback, support, or incident work.

One small habit makes this safer: after each release, confirm that the new version tag is in the registry before cleanup runs. That takes less than a minute and prevents the kind of mistake people only notice when they need an older build in a hurry.

Mistakes that lead to painful rollbacks

Audit Your Deployment Tags
Find risky moving tags like latest before they break a rollback.

The worst cleanup mistakes do not show up on calm days. They show up when a deploy breaks login at 6 p.m. and the image you need is already gone.

One of the most common mistakes is treating latest as the only tag worth keeping. That tag moves every time you push. If a bad build replaces it, your clean rollback point disappears with it. Keep tags that point to a specific build, commit, or release. latest can stay, but it should never be your only safety net.

Teams also keep too little history from the main branch. This hits fast-moving projects first. If you deploy ten or twenty times a day and keep only the last three main images, you may delete the last known good build before anyone realizes there is a problem.

Broad patterns cause a different kind of mess. A rule meant to clean up branch tags can catch release tags if naming is sloppy. A pattern that matches anything starting with v or release can wipe images you planned to keep for months. Test patterns against real tag names before you save the rule.

Security and compliance work create another risk. Sometimes the team needs older images for an incident review, an audit trail, or a dependency check. If cleanup removes them too early, you lose more than disk space. You lose evidence.

Tag changes can also break cleanup in a quiet way. A team renames tags from prod-123 to stable-123 and forgets to update retention rules. GitLab keeps following the old pattern, and the new tags drift into the delete pile.

A short sanity check prevents most rollback pain:

  • Keep fixed release tags, not only moving tags
  • Keep enough recent main images for your deploy pace
  • Exclude release and hotfix tags from broad cleanup patterns
  • Match retention windows to security review timelines
  • Update rules whenever tag names change

If you cannot say which tag you would roll back to today, the rule is too aggressive.

Checks to do before you save

Get Hands On CTO Help
Work with Oleg on GitLab, infrastructure, and safe production workflows.

Before turning on cleanup, look at the tags your production systems use right now. Not the tags you expect. The tags actually running in production. If your deploy process still points to latest, a branch name, or another moving tag, cleanup can remove the image you need for a safe rollback.

A good retention rule keeps storage under control without forcing the team to rebuild an old image during an incident. Rebuilding sounds fine until a dependency changed, a base image moved, or the old commit no longer produces the same result. For rollback and forensics, the exact image matters.

Check a few things before you save anything:

  • List the current production tags for every app and environment that matters, including workers, cron jobs, and other separate images
  • Confirm you can roll back one release by pulling an existing image instead of rebuilding from old code
  • Make sure branch, merge request, test, and release tags are easy to tell apart
  • Compare your retention window with the real calendar, including long weekends, holidays, and slow approval cycles
  • Ask someone outside the build team to review the rule

That last check is often the most useful. An ops lead, engineering manager, or fractional CTO will often spot risk faster because they see how deployments happen in practice, not just how CI is supposed to work.

A simple example shows why this matters. A team keeps main-<sha> images for testing and release-2026-04-10 for production. Their cleanup rule deletes untagged images and branch tags after five days but keeps release tags. That looks safe until they notice a worker service in production still pulls a main-<sha> tag. One quick review catches the problem before cleanup does real damage.

If you cannot answer these checks with a clear yes, wait. Tightening retention is easy. Recovering from a deleted rollback image is not.

Watch the first week closely

Once cleanup starts running, the first week tells you a lot. Watch storage each day, but do not judge the rule by saved space alone. After every deploy, ask one practical question: if production breaks tonight, do we still have the image tag we trust for a rollback?

A smaller registry bill is nice. A safe rollback matters more. If engineers start keeping extra tags by hand because they do not trust the rule, the policy is too tight or the naming plan is still unclear.

Use real deploy history to tune the window. Teams often guess wrong. They assume they only need the last few images, then a hotfix or customer issue sends them back to a build from twelve days ago.

If your app deploys from main many times a day but rollbacks almost always use release tags from the last two weekly releases, keep release tags longer and expire short-lived CI tags faster. If nobody has ever rolled back to a feature branch image after merge, let those go sooner.

After the first week, review a few basics:

  • Did storage drop enough to justify the rule?
  • Did any deploy, rollback, or incident review need an image that cleanup removed?
  • Are release and hotfix tags still easy to find?
  • Are people inventing manual keep-tags because the system does not fit real work?

Then write the tag plan down in plain language. Keep it short. Define which tags stay, which expire, how long hotfix images remain, and who can create permanent tags. New team members will follow a short written rule far more often than an old chat message.

Do not change everything at once. Adjust one retention setting, wait a few days, and see what happens. Small changes are easier to trust, and they make mistakes easier to spot.

If your GitLab setup, release flow, or retention policy still feels messy, Oleg Sotnikov at oleg.is offers Fractional CTO and startup advisory help for teams sorting out CI/CD, infrastructure, and safe rollback practices. Sometimes an outside review is the fastest way to cut storage waste without creating new risk.