Upgrading Self-Managed GitLab from Older Versions

A disciplined upgrade path, node sequence, and operational checks for bringing a 15.2.x GitLab 5,000 User Reference Architecture up to the current N-1 release.

This guide is intended for customers running the GitLab 5,000 User Reference Architecture who need to bring a 15.2.x instance up to the current N-1 release. It assumes you have operational ownership of the environment and working familiarity with the component topology.

A major version jump across a multi-node, highly available GitLab deployment is a significant undertaking, but it is entirely achievable in-house with disciplined planning. What follows is the upgrade path, the node sequence, and the operational checks we recommend you build your maintenance windows around.

Step 1: Establishing the Upgrade Path

GitLab releases contain background migrations, schema changes, and deprecations that make direct version jumps unsafe. You cannot move from 15.2.x to the latest release in a single hop; the upgrade must be performed in stages against defined required stops.

Use the official GitLab Upgrade Path tool, maintained by the GitLab Support team, to generate the authoritative path for your environment. Input your current version (15.2.x) and your target (N-1). Based on standard GitLab upgrade rules, your hop sequence from 15.2.x typically looks like this:

15.2.x -> 15.4.6 -> 15.11.13 -> 16.3.8 -> 16.7.z -> 16.11.z -> 17.3.z -> 17.8.z -> Target (N-1)

Replace .z with the highest available patch release for that minor version. We recommend you re-validate the path against the Upgrade Path tool immediately prior to the maintenance window, as patch versions move frequently.

Step 2: Reference Architecture Considerations

The 5,000 User Reference Architecture is a distributed deployment, so this is not a matter of running apt-get upgrade gitlab-ee against a single host. The components in scope are:

  • Consul nodes
  • Redis (HA / Sentinel)
  • PostgreSQL / Patroni cluster
  • PgBouncer
  • Praefect / Gitaly cluster
  • A designated Deploy Node
  • GitLab Application nodes (Sidekiq, Puma/Rails)

The Golden Rule: Background Migrations

Between every hop in the upgrade path, all Batched Background Migrations must be fully complete before you proceed. Moving to the next hop while migrations are still in flight risks database corruption and failed upgrades, and recovery from that state is costly.

You can verify completion through the UI under Admin Area > Monitoring > Background Migrations, or on the Deploy Node with:

sudo gitlab-rake gitlab:background_migrations:status

Treat this as a mandatory gate, not a guideline.

Step 3: The Multi-Node Upgrade Sequence

For each hop in your upgrade path (for example, 15.2.x to 15.4.6, then 15.4.6 to 15.11.13, and so on), execute the following sequence end-to-end before beginning the next hop.

1. Backups

Before any hop, take VM-level snapshots or execute a full backup of your PostgreSQL database, configuration (/etc/gitlab/gitlab.rb and /etc/gitlab/gitlab-secrets.json), and filesystem data. This is your rollback position; do not proceed without it.

2. Upgrade the Stateful Components (Bottom-Up)

Stateful components are upgraded first so that the application layer is not pointing at a cluster in an inconsistent state. Apply the GitLab package upgrade (apt-get install gitlab-ee=<version>) to nodes in the following order:

  1. Consul Nodes: Upgrade one at a time. Confirm cluster health before proceeding to the next node.
  2. Redis/Sentinel Nodes: Upgrade replicas first, then fail over the primary to an upgraded replica, then upgrade the former primary.
  3. PostgreSQL / Patroni Nodes: Upgrade replicas first. Fail over the primary leader, then upgrade the former leader.
  4. PgBouncer Nodes: Upgrade concurrently or as a rolling operation.
  5. Gitaly Cluster (Praefect + Gitaly): Upgrade Praefect nodes first, followed by the Gitaly backend nodes.

3. Run Pre-Deployment Migrations on the Deploy Node

The Deploy Node is a designated Rails node responsible for database schema changes. At this stage, run the pre-deployment migrations only; defer post-deployment migrations until the application tier is upgraded.

sudo touch /etc/gitlab/skip-auto-reconfigure
sudo apt-get install gitlab-ee=<version>
sudo SKIP_POST_DEPLOYMENT_MIGRATIONS=true gitlab-ctl reconfigure

4. Upgrade the Application Nodes

With the stateful tier and Deploy Node in place, upgrade the nodes serving traffic:

  • Sidekiq Nodes: Upgrade the package and run sudo gitlab-ctl reconfigure.
  • GitLab Web/API Nodes (Rails): Upgrade the package and run sudo gitlab-ctl reconfigure.

5. Finalise Migrations

Return to the Deploy Node and execute the post-deployment migrations:

sudo gitlab-rake db:migrate

6. Verify and Wait

Before starting the next hop:

  • Confirm cluster health through the GitLab UI.
  • Wait for all background migrations to complete. Some hops may require you to manually finalise a migration via a rake task if it stalls. Monitor the Batched Background Migrations dashboard closely at this stage.

Do not begin the next hop until both conditions are satisfied.

Additional Considerations

Moving from 15.2 into the 17.x / 18.x range crosses several architectural changes. The following items are worth flagging into your runbook:

  • PostgreSQL Version Upgrades: GitLab 15.x to 16.x involves an automated PostgreSQL upgrade (typically 13 to 14). On a Patroni cluster this is not fully automated; you will need to invoke the PostgreSQL upgrade manually using gitlab-ctl pg-upgrade on your Patroni nodes within the maintenance window.
  • Gitaly / Praefect Changes: Praefect’s database tracking has been optimised across several releases. Ensure Praefect database migrations have completed in full before upgrading the Gitaly backend nodes.
  • Elasticsearch / OpenSearch: If you use Advanced Search, verify that your Elasticsearch version is supported by the target GitLab version. Major GitLab version boundaries frequently drop support for older Elastic releases; update the search cluster before crossing those boundaries.

Closing Notes

A 5,000 user GitLab upgrade from 15.2.x to N-1 is a sequence of carefully staged hops rather than a single event. The work is front-loaded into planning: confirm the upgrade path, respect the node ordering, gate every hop on background migration completion, and keep a clean rollback position at each stage.

Tail gitlab-ctl tail throughout the window, keep your runbook open, and validate health between hops rather than at the end. Executed patiently, this is a controlled, low-risk operation.

If you hit issues during execution that fall outside the scope of this guide, the GitLab documentation and community resources are well-maintained, and our team is available to support you on the hops where you want a second pair of eyes.

Learn more about our GitLab Upgrades service, or get in touch if you’d like a second pair of eyes on your upgrade plan.