Upgrading GitLab installed with the Helm chart

A planning guide for teams upgrading cloud native GitLab on Kubernetes, covering chart-to-version mapping, runner order, required stops and the choice between zero-downtime and single-downtime upgrades.

On this page

Why a GitLab Helm chart upgrade needs its own plan

A self-managed GitLab running on Kubernetes that sits behind the current stable line should be upgraded by mapping the chart version to the GitLab version, moving one minor release at a time through each required stop, and then choosing either a zero-downtime two-pass helm upgrade or a single upgrade that accepts an outage. The first decision is the one most teams skip. GitLab Helm chart versions do not match GitLab versions, so a chart number that looks close to the target release is not a safe guide. The published version mappings tell you which chart release carries which GitLab release, and the supported route between your current version and the target comes from the GitLab upgrade paths documentation and the maintenance policy, not from the chart tag alone.

The route matters because GitLab requires upgrades to pass through required upgrade stops, which since GitLab 17.5 fall at versions x.2, x.5, x.8 and x.11. An instance several versions behind must therefore stop at each of those points in order, with background migrations completed before the next hop. Confirm the current stop list in the upgrade paths documentation before you write any plan, because a stop that is skipped cannot be recovered by a later helm upgrade. Check the GitLab maintenance policy as well, since it sets which minor lines receive fixes and therefore which intermediate releases are worth the time of a hop.

Plan the chart work as its own change, separate from the application work. Export the live configuration with helm get values before touching anything, keep the values file minimal so that defaults can move between chart releases, and upgrade GitLab Runner first, as the chart procedure requires. Your team needs to decide early whether the business can accept downtime, because the zero-downtime path needs multiple Webservice and Sidekiq replicas and two sequential helm upgrade runs, which means more operator time and more rollback points to test. Ask your platform owner to confirm the cluster's replica counts and the chart's documented requirements for each hop before the change window is booked.

What changes between GitLab versions and what each change asks of you

This table compares the recurring release types, the maintained lines and the required upgrade stops, with the action each one asks of a chart-based upgrade. Read it to decide how often you plan a chart upgrade and which target versions need a stop. The main takeaway is that a Helm upgrade must land on a required stop, and the chart version must match the GitLab version you target.

ChangeWhat it isWhat it asks of you
Major releaseGitLab ships one major release yearly, with 20.0 planned for May 2027.Plan a major version change as a separate project and confirm chart and component requirements in the release notes for 20.0.
Minor releaseA minor release ships on the third Thursday of each month.Decide a cadence for moving within the line, and check the chart version mapping before each change.
Patch releasesPatch releases ship twice a month.Schedule regular patch upgrades within your target line, since security fixes reach the previous two monthly releases.
Maintained linesGitLab currently maintains 19.5, 19.4 and 19.3.Keep your instance on a maintained line, and confirm which line your chart version supports before you start.
Required upgrade stopsSince 17.5, upgrades must pass through x.2, x.5, x.8 and x.11, for example 18.2, 18.5, 18.8, 18.11, 19.2, 19.5, 19.8 and 19.11.Stop at each required version in order, applying one Helm upgrade per stop, and confirm background migrations finish between stops.
Chart-to-GitLab mappingChart versions do not match GitLab versions, so each chart release maps to a GitLab release.Look up the mapping for your target GitLab version and pin the chart version before running helm upgrade.
Zero-downtime stepsZero-downtime chart upgrades go one minor release at a time, with a first upgrade that skips post-deployment migrations.Confirm you have multiple Webservice and Sidekiq replicas, then run the second upgrade for post-migrations.
Runner alignmentGitLab Runner should match the GitLab major and minor version.Upgrade runners first, as the chart procedure requires, and confirm the runner version for each target stop.

Zero-downtime or single-downtime: choosing the helm procedure

The zero-downtime procedure keeps users working while the chart moves to the next minor release. It runs two helm upgrades. The first upgrade rolls out the new chart and images with post-deployment migrations skipped, so the running Webservice and Sidekiq pods keep serving traffic on compatible code. The second upgrade runs the post-deployment migrations and completes the change. The procedure only works when the environment can absorb pods being replaced one at a time, so it suits production instances with users who cannot accept a planned outage.

  • Replica count: Webservice and Sidekiq need more than one replica each so that some pods stay available while others restart.
  • Version path: Move one minor release at a time, and respect the required upgrade stops for the GitLab version you are crossing.
  • Two-pass sequence: Run the first helm upgrade with post-deployment migrations skipped, check that pods are healthy, then run the second upgrade for post-migrations.
  • Runner order: Upgrade GitLab Runner before the server, keeping major and minor versions aligned.
  • Database and storage readiness: Confirm that PostgreSQL, Redis and object storage are sized and reachable throughout the rollout, since a major PostgreSQL upgrade falls outside this procedure.

Before starting, confirm the replica counts, the target minor release and the rollback path with your platform team, and check the upgrade documentation for the exact flags in your chart version.

Preparing the cluster, backups and values before the first helm command

Most failed chart upgrades trace back to work done before the first helm command. The cards below cover what to capture, what to rehearse and what to confirm, so that rollback and troubleshooting start from a known state. Work through them in order, because later steps depend on the backup and exported values from earlier ones.

Take and verify a backup

Run a full GitLab backup as described in the backup and restore documentation before anything changes in the release. Store the archive outside the cluster so that a node or volume failure does not take the backup down with the instance. A backup that has never been restored is only a hope, so restore it into the test environment and confirm that projects, repositories and registry data are present. Confirm separately how your deployment captures secrets, because the backup alone may not hold everything needed to read stored data.

Export the current values

Run helm get values <release> -n <namespace> -o yaml > values-before.yaml before you change anything. This captures the overrides the running release actually uses, including changes made by earlier upgrades or by someone editing the cluster directly. Keep the file in version control next to the rest of your deployment code, and record the chart version currently deployed so you can return to it if the upgrade must be reversed.

Keep the values file minimal

Build the file for the new chart from only the settings you deliberately changed. A full dump freezes the old chart's defaults into your configuration, so new defaults in the target chart never take effect. Compare the exported file with the target chart's default values, keep each override with a comment explaining why it exists, and remove any override that now matches the default. Confirm the target chart version against the published mapping, since chart versions do not match GitLab versions.

Rehearse in a mirror environment

Build a test environment that runs the same chart version and the same GitLab version as production, with the same Webservice and Sidekiq replica counts where you can. Apply the planned upgrade there first and time each step, including both passes of the zero-downtime procedure if you plan to use it. Restore a recent production backup so migrations run against data shaped like production. Record every error and manual step, because these become the runbook for the production window.

Confirm storage and database versions

Check the database and storage prerequisites for your target GitLab release in its upgrade documentation before you schedule the window. Newer releases can raise minimum versions for components such as PostgreSQL, and an upgrade that is otherwise correct can stall on a version your cluster does not meet. Ask your platform team to record the current versions of your bundled or external PostgreSQL and any other stateful services, then list the gap to each requirement as a pre-upgrade task.

Runner first, maintenance mode optional

Upgrade GitLab Runner before the GitLab server, because the documented steps place the runner upgrade ahead of the chart upgrade, and runner major and minor versions should stay aligned with GitLab. Decide whether to enable maintenance mode before the first pass. It blocks writes for the window and is optional for zero-downtime upgrades, but it gives a clean stopping point when a migration runs long or the rollback decision is still open. Record that decision in the change record.

The upgrade sequence, with checks and rollback points

This sequence moves a cloud native GitLab release one minor step at a time, with a check and a rollback point at each stage so the team can stop safely before the next change. Each required stop repeats the same loop.

  1. Take a verified backup before any change

    The platform team takes a GitLab backup with the backup utility and stores it outside the cluster, then confirms the archive exists and is readable. Also capture the Kubernetes secrets and the configuration that GitLab depends on, because a backup of application data alone may not be enough to restore a working instance. This backup is the only reliable rollback point in the sequence. If you cannot restore it into a test environment, treat the rollback path as unproven. Confirm the exact backup scope for your chart version in the GitLab backup documentation.

  2. Enable maintenance mode if your users need it

    Maintenance mode is optional. Enable it when you want users to stop writing during the upgrade, for example when you cannot guarantee zero-downtime behavior for your topology or when you are using a single-node deployment. Check that the banner appears and that API and Git write requests are blocked as expected. The rollback step for this stage is to disable maintenance mode once the upgrade is confirmed or abandoned, and the team should record the time it was turned on so the change window is documented.

  3. Upgrade GitLab Runner before the server

    Upgrade the GitLab Runner fleet first, keeping its major and minor version aligned with the GitLab release you are moving to. Runners that are older than the server can fail to pick up or report jobs in ways that are hard to diagnose after the server changes. Run a test pipeline on one runner from each executor type and confirm that jobs start, log output appears and artifacts upload. If a runner fails this check, roll back that runner to its previous version, because the server has not changed yet and no migration has run.

  4. Export current values with helm get values

    Run helm get values against the release and save the output to a versioned file in your configuration repository. Compare it with the values file you intend to use for the target chart version, and remove any setting that the new chart version no longer needs. Keep this export as the reference for the rollback path, because a helm rollback restores the previous release revision but does not replace your own record of what was configured. Store the file with the backup reference so both can be found together.

  5. Run the first helm upgrade with post-deployment migrations skipped

    Run the first helm upgrade to the target chart version with post-deployment migrations skipped. The Webservice and Sidekiq pods roll forward while the database changes that must run after rollout are held back. Watch the rollout until all deployments report ready, and confirm that the release revision shows as deployed in helm history. This is the first point where the cluster state changes in a way the backup must cover, so if pods fail to become ready, use helm rollback to the previous revision and restore data from the backup only if the database was altered.

  6. Check health before the second pass

    Before running the post-migration pass, check the instance from outside the cluster. Confirm that the web UI loads, that a test user can sign in, that a Git clone and push succeed, that a CI job runs on an upgraded runner, and that the GitLab health endpoints and pod logs show no repeated errors. Check the database migration status in the Admin area. If any check fails, stop here. The rollback point is still the previous revision plus the backup, and no post-deployment migration has run yet.

  7. Run the second pass for post-deployment migrations

    Run the second helm upgrade with post-deployment migrations enabled, using the same chart version and values. This applies the migrations that were held back in the first pass. Watch the migration job until it completes successfully, then repeat the health checks from the previous step. Once post-deployment migrations have run, a helm rollback to the older chart revision is no longer a clean path, so the restore from backup becomes the realistic recovery option. Confirm that the target version appears in the Admin area and that background migrations finish before any further stop.

  8. Repeat the loop for each required upgrade stop

    If the instance is behind a required upgrade stop, repeat the sequence for each intermediate minor release on the path, one at a time, rather than jumping to the final version. Review the GitLab upgrade path documentation for the current stops, and do not begin the next hop until the previous one shows healthy and background migrations are finished. Record the release, chart version, runner version, backup reference and check results for each hop. This record is the evidence trail for the change and the basis for any restore decision.

How the Kubernetes layer shapes the upgrade

The Kubernetes cluster under the chart sets limits on when and how you can upgrade GitLab, so check it before you plan the chart change. The version skew policy requires kube-apiserver to move one minor version at a time, and kubelets may run up to three minor versions older than kube-apiserver. If your nodes lag behind the control plane, a cluster upgrade may need to come before the GitLab change, and that work belongs in the same plan. Confirm which Kubernetes minor versions your provider supports, because the project maintains only the three most recent minor releases. As of September 2026, those were 1.37 (end of life October 28, 2027), 1.36 (June 28, 2027) and 1.35 (February 28, 2027), according to kubernetes.io/releases. Also confirm the version your chart release targets with the GitLab chart documentation, linked from the upgrade procedure.

Chart secrets need protection before the upgrade starts. Kubernetes stores Secrets unencrypted in etcd by default, and the GitLab chart relies on Secrets for items such as the root password, database credentials and object storage keys. Ask the platform team whether encryption at rest is enabled for etcd, who holds list and watch access to the GitLab namespace under least-privilege RBAC, and whether an external store such as the Secrets Store CSI Driver is used. Review these settings before the helm get values export, since exported values can reveal references to sensitive material.

The chart scope also depends on where PostgreSQL and Redis run. The GitLab reference architectures state that running stateful components such as PostgreSQL and Redis inside Kubernetes is not supported, and the Cloud Native Hybrid architecture keeps those services on VMs or managed services. A helm upgrade changes only the stateless GitLab components on the cluster. Database and Redis changes happen outside the chart, so confirm their versions and maintenance windows separately before you schedule the chart upgrade.

What makes a chart upgrade take longer

How many required upgrade stops affect the effort of a GitLab chart upgrade?

The number of required upgrade stops between your current and target versions is the first driver of effort, because each stop is a separate planned hop with its own validation. Since GitLab 17.5, required stops fall at x.2, x.5, x.8 and x.11, so a jump from 18.2 to 19.5 crosses several of them, while a jump within one stop interval is a single hop. Each hop needs its own chart version mapping, backup, pre-upgrade checks and post-upgrade testing. Inventory your current version, the target version and every stop between them, then check the upgrade paths documentation for any stop-specific steps. Ask any partner to price the hops individually so you can see how the count changes the quote.

Do custom values and overrides make a GitLab Helm upgrade harder?

Yes. Custom values and overrides increase effort because every setting you changed must be checked against the new chart version, and some keys may be renamed, deprecated or given new defaults. Teams that have accumulated long values files often find settings nobody can explain, which slows review and testing. Export the live configuration with helm get values, compare it with the chart defaults for each target version, and separate the settings you still need from the ones left over from earlier installs. A smaller, documented values file usually shortens the work and makes the diff reviewable.

How do external PostgreSQL and Redis change the upgrade plan?

External PostgreSQL or Redis adds a second system with its own version, backup schedule and maintenance window, so the upgrade has more moving parts. GitLab's supported database and Redis versions for each target release must be confirmed before the chart upgrade starts, and a database major version change is a separate project that falls outside the zero-downtime chart procedure. Inventory the engine versions, replication topology, backup tooling, who owns each service and whether the database team can take a change window. Ask for these items to be quoted separately, because they are often owned by a different team and scheduled on a different calendar.

Does the size of the runner fleet affect a GitLab chart upgrade?

The runner fleet affects effort because the documented steps upgrade GitLab Runner before the server, and runners must keep the same major and minor versions as GitLab. A small fleet of one or two runners can be updated quickly, while a fleet with several executor types, such as shell, Docker and autoscaling runners on cloud VMs or Kubernetes, needs each executor path tested. Autoscaling runners add work because their images, registration settings and cloud permissions must be verified. Inventory every runner, its executor, its host or cluster, and the owner of each one, then decide whether runner upgrades belong in the same change or in a separate one.

How do Geo or multi-site setups lengthen an upgrade?

A Geo or multi-site setup lengthens the upgrade because each site has to be sequenced, verified and kept consistent with the others, and replication must be handled deliberately. Upgrade order across sites, pausing replication to keep a clean recovery checkpoint and matching secrets between sites all add steps that a single cluster does not need. Geo is available in the Premium and Ultimate tiers for self-managed GitLab, according to the GitLab Geo documentation. Inventory the number of sites, the replication status, the disaster recovery runbook and the change windows each site allows. Ask for the Geo upgrade procedure to be scoped as its own work package with its own test plan.

Why does the amount of data needing background migrations change the timeline?

The amount of data waiting on background migrations changes the timeline because these jobs run after an upgrade and must finish before the next required stop can be taken safely. A large instance with many projects, pipelines or artifacts can take much longer to finish them than a small one, so the time between hops grows with data volume. Check the migration status in the Admin area or the database before each hop, and estimate the work from your own instance size and job history rather than from a generic figure. Ask any partner how they will measure migration progress and what they will do if a migration fails or stalls.

What should I inventory before asking for a quote on a chart upgrade?

Before requesting a quote, inventory the current and target GitLab and chart versions, the list of required stops between them, and every custom value or override in the live release. Record the external database and Redis versions and owners, the runner fleet with executor types and hosts, whether Geo or other sites are involved, and the approximate size of the instance and its pending background migrations. Also note the backup location, the maintenance mode policy and the change windows your business allows. A written scope built from this list lets each vendor quote the same work, which makes comparisons fair.

Where to confirm chart and version details

Before any upgrade run, confirm the chart and version details against the target release, because the mapping between GitLab Helm chart versions and GitLab versions and the list of required upgrade stops both change over time. Start with the GitLab Helm chart upgrade documentation, which sets out the steps for backup, optional maintenance mode, upgrading GitLab Runner first, and exporting current values with helm get values. Record the chart version currently deployed and the chart version that maps to your target GitLab release, and confirm both in that document rather than relying on a version you noted during planning.

Next, check the path between your current release and the target. The upgrade paths documentation lists the required stops that the instance must pass through, and it should be read in full for every hop in the sequence, not only the final version. Cross-check the stops against the GitLab maintenance policy, which explains which releases receive patches and security fixes at a given time. A release that was supported when you began planning may be out of support by the day you run the upgrade, so confirm the current list when you schedule the change window.

Keep a dated record of the versions you confirmed, the source pages you checked and the values file you exported, and attach it to the change ticket. Ask your partner or internal owner to repeat these checks on the day of the upgrade, since a new patch or a revised mapping published in the interim can alter the sequence. This record also gives auditors and reviewers evidence of how the target release was chosen.

How DeployOpen scopes and delivers a GitLab chart upgrade

DeployOpen plans and delivers the upgrade of a GitLab instance installed with the Helm chart inside your own Kubernetes cluster and cloud accounts or data centers. Each engagement starts from a written scope that fixes the current and target versions, the chart mapping, the values files and the verification steps before any change is made to production.

How we scope

  • Record the installed chart version, GitLab version, Runner versions and the output of helm get values for each release.
  • Map the current chart to the target GitLab version and list every required upgrade stop between them.
  • Confirm Webservice and Sidekiq replica counts, load balancer behavior and whether a maintenance window is acceptable.

How we build

  • Prepare a minimal values file that carries only the settings your instance needs, tested in a non-production cluster first.
  • Run a pre-upgrade backup check, upgrade GitLab Runner first, then execute the planned helm upgrade sequence.
  • Test sign-in, repository access, CI pipelines, container registry and API calls against a written checklist after each stop.

How we hand over

  • Deliver a runbook with exact commands, rollback points, decision gates and the verification results for each stop.
  • Document the values file, chart version pins and any deviations from the default procedure for your platform team.
  • Walk your operators through the procedure so the next upgrade can be run and reviewed by your own team.

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers after the initial engagement ends.
  • Engagements are fixed-scope, so changes to the agreed scope are written down before additional work starts.
  • Confirm with DeployOpen during scoping which support hours, response expectations and upgrade cadence apply to your retainer.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.