Managing Releases and Rollbacks

Upgrade, rollback, and manage Helm releases like a pro. Understand release history and revision management.

7 min read

Managing Releases and Rollbacks

In the previous tutorial, we learned how hooks let you run tasks at specific lifecycle events. Now let's zoom out and understand releases as a whole — how Helm tracks them, how upgrades work, and how to roll back when things go wrong.

What Is a Release?

Every time you helm install, Helm creates a release — a running instance of a chart with a specific configuration. Think of it as chart + values + revision number.

# Create a release named "prod-api"
helm install prod-api ./my-chart -f production.yaml

# Create another release of the SAME chart
helm install staging-api ./my-chart -f staging.yaml

These are independent releases. Upgrading prod-api doesn't affect staging-api.

Listing Releases

# List all releases in the current namespace
helm list

# Output:
# NAME        NAMESPACE  REVISION  STATUS    CHART          APP VERSION
# prod-api    default    3         deployed  my-chart-1.2.0 3.4.1
# staging-api default    1         deployed  my-chart-1.1.0 3.3.0

# List across all namespaces
helm list --all-namespaces

# Filter by status
helm list --failed
helm list --pending
helm list --deployed

# Filter by name
helm list --filter "prod.*"

Upgrading Releases

helm upgrade applies changes to an existing release:

# Upgrade with new values
helm upgrade prod-api ./my-chart -f production.yaml --set replicaCount=5

# Upgrade to a new chart version
helm upgrade prod-api ./my-chart --version 1.3.0

# Upgrade and install if it doesn't exist
helm upgrade --install prod-api ./my-chart -f production.yaml

That last one — --install (or -i) — is a gem. It installs on the first run and upgrades on subsequent runs. Perfect for CI/CD pipelines where you don't want to track whether it's a first deploy or not.

What Happens During an Upgrade

1. Helm renders templates with the new values
2. Helm compares the new manifests against the live resources
3. Pre-upgrade hooks run
4. Helm applies changes using a 3-way strategic merge:
   - Old manifest (from the last revision)
   - New manifest (from the current render)
   - Live state (what's actually in the cluster)
5. Post-upgrade hooks run
6. Revision number increments

The 3-way merge is important — if someone manually edited a resource in the cluster, Helm preserves those changes unless the new chart explicitly overrides them.

Upgrade Flags You Should Know

# Wait for all resources to be ready before marking success
helm upgrade prod-api ./my-chart --wait

# Set a timeout for --wait
helm upgrade prod-api ./my-chart --wait --timeout 5m

# Automatically roll back if upgrade fails
helm upgrade prod-api ./my-chart --atomic

# Dry run — see what would change without applying
helm upgrade prod-api ./my-chart --dry-run

# Show the diff (requires helm-diff plugin)
helm diff upgrade prod-api ./my-chart -f production.yaml

# Force resource updates (recreate if needed)
helm upgrade prod-api ./my-chart --force

# Reuse the values from the last release
helm upgrade prod-api ./my-chart --reuse-values

# Reset values to chart defaults, then apply overrides
helm upgrade prod-api ./my-chart --reset-values -f production.yaml

"What's --atomic do exactly?"

--atomic combines --wait with automatic rollback. If the upgrade fails (pods don't become ready, hooks fail, timeout exceeded), Helm automatically rolls back to the previous revision. It's the safety net you want in production.

The --reuse-values Trap

--reuse-values sounds convenient but has a sharp edge:

# First install with explicit values
helm install prod-api ./my-chart --set image.tag=v1.0

# Upgrade with --reuse-values
helm upgrade prod-api ./my-chart --reuse-values --set image.tag=v2.0

The problem? If the chart adds new default values in values.yaml, --reuse-values ignores them — it only uses the values from the previous release. New defaults are lost.

Prefer --reset-values with an explicit values file:

helm upgrade prod-api ./my-chart --reset-values -f production.yaml

Viewing Release History

Every upgrade creates a new revision:

helm history prod-api

# REVISION  UPDATED                   STATUS      CHART          APP VERSION  DESCRIPTION
# 1         Mon Jan 15 10:00:00 2024  superseded  my-chart-1.0.0 3.0.0        Install complete
# 2         Tue Jan 16 14:30:00 2024  superseded  my-chart-1.1.0 3.1.0        Upgrade complete
# 3         Wed Jan 17 09:15:00 2024  deployed    my-chart-1.2.0 3.2.0        Upgrade complete

By default, Helm keeps 10 revisions. You can change this:

# Keep 20 revisions
helm upgrade prod-api ./my-chart --history-max 20

# Or set it globally during install
helm install prod-api ./my-chart --history-max 20

Inspecting a Release

# See the values used for a release
helm get values prod-api

# See ALL values (including defaults)
helm get values prod-api --all

# See the rendered manifests
helm get manifest prod-api

# See the release notes (NOTES.txt output)
helm get notes prod-api

# See hooks
helm get hooks prod-api

# Get everything
helm get all prod-api

# Inspect a specific revision
helm get values prod-api --revision 2
helm get manifest prod-api --revision 1

Rolling Back

Something broke? Roll back to a previous revision:

# Roll back to the previous revision
helm rollback prod-api

# Roll back to a specific revision
helm rollback prod-api 2

# Roll back with safety flags
helm rollback prod-api 2 --wait --timeout 5m

Rollback Lifecycle

1. Helm retrieves the manifest from the target revision
2. Pre-rollback hooks run
3. Resources are restored to the target revision's state
4. Post-rollback hooks run
5. A NEW revision is created (rollback doesn't rewind the counter)

Important: rollback creates a new revision, it doesn't delete history:

helm history prod-api

# REVISION  STATUS      DESCRIPTION
# 1         superseded  Install complete
# 2         superseded  Upgrade complete
# 3         superseded  Upgrade complete (the broken one)
# 4         deployed    Rollback to 2    <-- new revision!

What Gets Rolled Back?

Helm rolls back the Kubernetes manifests — the YAML it sent to the cluster. It does NOT roll back:

  • Data in databases
  • Files on persistent volumes
  • External services or DNS records
  • Anything outside the cluster

This is why hooks are important — a pre-rollback hook could trigger a database restore, for example.

Uninstalling Releases

# Delete a release
helm uninstall prod-api

# Delete but keep the history (allows rollback to re-install)
helm uninstall prod-api --keep-history

# Dry run
helm uninstall prod-api --dry-run

With --keep-history, you can actually "roll back" a deleted release:

helm uninstall prod-api --keep-history
helm rollback prod-api 3   # Re-installs revision 3!

Release Statuses

StatusMeaning
deployedCurrently active revision
supersededPrevious revision (replaced by upgrade/rollback)
failedRevision that failed to deploy
uninstallingBeing deleted
pending-installInstall in progress
pending-upgradeUpgrade in progress
pending-rollbackRollback in progress

Where Are Releases Stored?

Helm 3 stores release data as Kubernetes Secrets in the release's namespace:

kubectl get secrets -l owner=helm

# NAME                           TYPE                 DATA
# sh.helm.release.v1.prod-api.v1   helm.sh/release.v1   1
# sh.helm.release.v1.prod-api.v2   helm.sh/release.v1   1
# sh.helm.release.v1.prod-api.v3   helm.sh/release.v1   1

Each revision is a separate Secret containing the compressed, base64-encoded release data (chart, values, manifest).

"Can I use ConfigMaps instead?"

Yes, but Secrets are the default because they're more restricted by RBAC. You can switch with:

export HELM_DRIVER=configmap

Production Workflow

Here's a typical production deployment workflow:

# 1. See what's currently deployed
helm list -n production

# 2. Preview the changes
helm diff upgrade prod-api ./my-chart -f production.yaml -n production

# 3. Upgrade with safety rails
helm upgrade prod-api ./my-chart \
  -f production.yaml \
  -n production \
  --atomic \
  --timeout 10m \
  --history-max 15

# 4. Verify
helm status prod-api -n production
kubectl get pods -n production

# 5. If something's wrong
helm rollback prod-api -n production --wait

What's Next?

You now know how to manage the full lifecycle of a release — install, upgrade, inspect, roll back, and uninstall.

In the next tutorial, we'll cover Helm repositories — where charts live and how to find, add, and manage chart repositories.