How to plan a GitLab 18 to 19 upgrade without guessing the path
A team running self-managed GitLab 18.x that needs to reach 19.x must pass through the 18.11 required upgrade stop, and the PostgreSQL 17 and Redis 7 prerequisites must be in place before that move starts. Those two conditions decide the order of everything else, so the plan begins by confirming the current version and the database and Redis versions in use, then working forward from there rather than picking a target and hoping the hops line up. Since GitLab 17.5, required upgrade stops fall at versions x.2, x.5, x.8 and x.11. For an instance on 18.x, that means 18.11 is the stop that matters for the move to 19.x, and the documented upgrade paths page is the source to check against your starting version before you schedule any hop. The 19.x line you are targeting should also be checked against the maintenance policy. At the time of the supplied facts, GitLab maintained 19.5, 19.4 and 19.3, and bug fixes reach only the current stable release. Confirm which 19.x release you will land on, because that choice determines which patch releases you install after the stop. The page does not treat every installation type the same way. The supplied facts cover the Linux package, Helm chart, Operator, Docker and source installs in general terms, but they do not give the per-method upgrade steps. Confirm the procedure for your installation method, and whether your PostgreSQL and Redis are bundled or external, with GitLab's own documentation and your own staging environment before you commit to a window.
What changes in GitLab 19 and what to do about it
This table compares each change that affects a self-managed GitLab 18 to 19 upgrade, with its impact and the action your team takes. Rows marked for verification are items the researched material does not confirm, so check them against the GitLab 19 release notes before you schedule work. The main takeaway: the required stops and database and Redis prerequisites set the upgrade order, and the API, registry and runner items need a staging instance on 19.x to test.
| Change | Impact | Action |
|---|---|---|
| PostgreSQL 17 before GitLab 19.0 | The GitLab database must be on PostgreSQL 17 before the 19.0 step. A major PostgreSQL upgrade falls outside the zero-downtime procedure, so it adds its own window. | Plan the database upgrade as a separate change for the bundled or external cluster. Confirm the server version before the 19.0 step. |
| Required upgrade stop at 18.11 | Instances on 18.x must pass through the required stops. The 18.11 stop is the last 18.x step before the 19.x line. | Upgrade to 18.11, confirm batched background migrations show Finished, then continue along the 19.x stops. |
| Redis 7 prerequisite | GitLab 19 requires Redis 7. The minimum patch level is not confirmed in the researched material. | Check the Redis requirement in the 19.0 release notes. Upgrade Redis for bundled or external deployments before the application step. |
| Removed bundled components | Components bundled in older packages may be removed or changed in 19.0. The specific list is not confirmed in the researched material. | Verify the removal list in the 19.0 release notes. Review gitlab.rb for settings that reference those components. |
| Operating system floors | Minimum supported operating system versions for 19.x may change. The exact floors are not confirmed in the researched material. | Verify the supported operating system list for 19.x in the installation requirements. Schedule OS upgrades ahead of the GitLab step. |
| API changes to test | Removed or changed API endpoints can break scripts, CI templates and integrations. The specific changes are not confirmed in the researched material. | Inventory API callers. Run them against a staging 19.x instance and verify each change in the release notes. |
| Container registry changes to test | Registry behavior or configuration may change in 19.x. The specific changes are not confirmed in the researched material. | Test pushes, pulls and cleanup policies in staging. Verify registry changes in the release notes before cutover. |
| Docker Machine runners (20.0 cleanup) | Docker Machine runner fleets are on the list to clear before GitLab 20.0 in May 2027, so they need a plan during the 19.x line. | Inventory runners that use Docker Machine and plan a move to a supported executor. Keep Runner major and minor versions aligned with GitLab. |
What to prepare before touching the production instance
These four to six items run in parallel and finish before any change reaches production. Each one produces evidence you will need at the go or no-go decision: a restore you have proven, a configuration you can account for, a rehearsal on matching topology, and a clear picture of what runs your CI jobs. Skipping any of them moves the risk into the maintenance window.
Prove a full backup and restore
Take a full backup of the instance and restore it onto a separate host before relying on it. Follow the backup and restore documentation, and remember that the backup does not capture everything, so confirm which secrets files and configuration you must keep alongside it. Record how long the restore took and whether repositories, issues, container registry data and CI artifacts came back intact. A backup that has never been restored is an assumption, not a rollback plan.
Inventory gitlab.rb and custom integrations
List every setting in gitlab.rb that differs from the defaults, along with external database, Redis, object storage and SMTP configuration. Add any custom hooks, webhooks, scripts, API clients, and single sign-on or LDAP settings that depend on the instance. Compare each entry against the release notes for 18.x and 19.0 and mark anything removed, renamed or deprecated. Keep this list in version control so the post-upgrade check has a baseline to compare against.
Build a test environment that matches production
Stand up a staging instance with the same install method, edition, topology and operating system as production, then restore your backup into it. Match the PostgreSQL and Redis versions you plan to run, the number of nodes, and any Gitaly or object storage layout. A test that runs on a single node will not show problems that appear in a multi-node deployment. Rehearse the full upgrade there first and time each step so the production window reflects what you measured.
Inventory CI runners and their versions
List every GitLab Runner registered to the instance, including its executor type, host operating system and version. The guidance is to keep Runner major and minor versions aligned with GitLab, so flag any runner that lags behind and plan its upgrade alongside the server work. Identify runners that depend on Docker Machine or registration token workflows, since those need separate attention. Confirm which projects and groups rely on each runner so you know who to notify before a restart.
Confirm batched background migrations are finished
Before moving to the next release, check that every batched background migration shows as finished. Look in the Admin area or query the database directly, and record the results. A migration that is still running or has failed can block the upgrade or leave data in an inconsistent state. Decide in advance how you will retry or finalize any failed migration, and do not start the production window until the list is clean.
Why the 18.11 stop and PostgreSQL 17 come before the jump
The upgrade cannot jump straight from 18.x to 19.x. GitLab requires upgrades to pass through required upgrade stops, and since GitLab 17.5 those fall at x.2, x.5, x.8 and x.11. For an 18 to 19 move, the instance must reach 18.11 first, complete its background migrations there, and only then move to the first 19.x release. Confirm the exact path against the GitLab upgrade paths documentation before you schedule anything, because the documented path is the authority for your starting version. Plan each hop as a separate change with its own backup and rollback point.
PostgreSQL 17 must be in place before GitLab 19.0, whether the database is the bundled one or an external cluster you manage. Treat this as a prerequisite change, not something the GitLab upgrade will do for you. Check the current PostgreSQL version on the primary, and confirm with GitLab which PostgreSQL version the 19.0 release requires and whether the bundled database is handled differently in your installation method. Major PostgreSQL upgrades are also excluded from the zero-downtime procedure, because they change the on-disk format and typically need a dump-and-restore, pg_upgrade or logical replication approach with a planned write freeze. That means a separate maintenance window, a rehearsed rollback and a fresh backup taken just before the cutover, even on a multi-node deployment that otherwise upgrades without downtime.
Redis 7 is the other component to verify, and the check is for the target version, not only the one you run today. Confirm in the 19.x release notes and installation requirements which Redis major version the target release supports, and whether your Redis (bundled or external, including any Sentinel setup) meets it. Record the result alongside the PostgreSQL check so both prerequisites are signed off before the 18.11 stop begins. A prerequisite that is only discovered during the 19.0 step leaves you with a half-upgraded instance and a rollback that may not be clean.
The upgrade sequence from 18.x to 19.x with rollback points
This sequence moves a self-managed GitLab instance from 18.x to a 19.x release one required stop at a time. Each stop closes with a verification check and a named rollback point, so the team can return to a known state if a check fails.
Confirm current version and migrations
Record the running GitLab version on every node, along with the node roles and the Runner versions in use. Confirm that the upgrade path from the current version passes through the required stops, using the GitLab upgrade paths documentation. Check that every batched background migration shows Finished in the Admin area or the database, because unfinished migrations can block the next stop. Done means a signed-off record of versions, nodes and migration status exists. This record is the starting state for every rollback decision that follows.
Back up and test restore
Take a full backup with the GitLab backup task and store the configuration files and secrets files separately, following the GitLab backup and restore documentation. Restore that backup into a separate test environment built to match production. Confirm that users can sign in, repositories clone, and a test pipeline runs on a Runner. Done means the restore has been tested end to end. This tested backup is the primary rollback point for the entire sequence.
Upgrade PostgreSQL and Redis prerequisites
Move the database to PostgreSQL 17 and the Redis service to Redis 7 before any GitLab 19 installation, whether they run on the bundled services or on external clusters. Confirm the supported PostgreSQL and Redis versions for your current GitLab release in the upgrade documentation before changing either. A major PostgreSQL upgrade falls outside the zero-downtime procedure, so schedule a maintenance window for it. Done means both services report the required versions and GitLab health checks pass. Take a snapshot of the database host before starting, and keep the tested backup as the fallback.
Upgrade to 18.11 and verify
Take a snapshot of every GitLab node, then upgrade to the 18.11 required stop, one minor release at a time. Run the post-upgrade migrations and confirm that background migrations finish before leaving this stop. Run the GitLab health check task, confirm sign-in, and run a test pipeline. Done means the instance reports 18.11, all migrations show Finished, and the checks pass. If a check fails, restore the snapshot from this stop or the tested backup from step two.
Upgrade to the 19.x target
From 18.11, the next required stop on the published path is 19.2, and later stops follow the x.2, x.5, x.8 and x.11 pattern. Choose a 19.x target that is in the currently maintained releases listed in the GitLab maintenance policy, and confirm the release notes for that version before starting. Take a snapshot before each stop, and verify version, migration status and health after each one. Done means the instance runs the chosen 19.x release with all migrations finished. Each stop's snapshot is its rollback point.
Run API, registry and runner checks
Test each API client and automation script against the upgraded instance, using the token scopes and endpoints your teams actually call. Push and pull test images through the container registry, and confirm that Runner versions match the GitLab major and minor version. Run a pipeline on each executor type in use. Review the 19.x release notes for API and registry changes, and confirm each one in your test environment. Done means every check has a recorded result. If a failure cannot be fixed in the maintenance window, the decision to roll back to the snapshot from the 19.x stop is made before users resume work.
Questions teams ask before upgrading GitLab 18 to 19
Can the GitLab 18 to 19 upgrade be quoted as a fixed price?
Yes, a fixed quote is possible once the scope is written down. Most DeployOpen engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts. The main cost drivers are the number of instances and nodes, whether PostgreSQL and Redis are bundled or external, how far the current instance sits from the 18.11 stop, how many integrations and runners need verification, and whether the environment is air-gapped. Costs fall into two groups: one-time work to plan, rehearse and perform the upgrade, and any recurring support or retainer you choose afterward. DeployOpen does not publish a price list, so ask for a quote built from a written scope that lists each driver and the test evidence you will receive at the end.
How long does a GitLab 18 to 19 upgrade take?
Duration depends mostly on the path, the environment and the rehearsal results, so no single figure applies to every instance. GitLab requires upgrades to pass through required stops at x.2, x.5, x.8 and x.11, so an instance on an early 18.x release must pass several stops, including 18.11, before 19.0. GitLab's upgrade paths documentation lists the stops. Time also depends on how long each stop takes on your database, how long background migrations take to finish between stops, and how many nodes you update in sequence. Measure each hop on a copy of production before setting a window. Ask any partner to state its per-hop timing assumptions in the written scope so you can compare them with your own test results.
What does a GitLab 18 to 19 upgrade need from our internal team?
The internal team provides decisions, access and knowledge of how GitLab is used. The work usually needs:
- A named owner who approves the change window, the rollback criteria and the cutover
- Access to the hosts, load balancers, DNS, database and object storage that GitLab depends on
- People who know the integrations, including runners, SSO or LDAP, Kubernetes clusters and CI pipelines
- Test users, projects and service accounts that exercise the API, the registry and CI jobs
- Permission to take and restore backups in a non-production copy
Agree on who signs off each required stop before the work begins, because a delay at one stop moves the whole schedule.
Can our own team upgrade GitLab from 18 to 19 without outside help?
A team that already runs GitLab and has practiced restores can do the upgrade itself, provided it covers the prerequisites and has time to rehearse. The prerequisites include PostgreSQL 17 and Redis 7 readiness, the 18.11 stop, the removal of bundled components and operating systems that your instance may depend on, and API and registry testing. Ask whether the team has upgraded across several required stops before, whether it has restored a backup within an agreed window, and who decides on rollback during the change. Outside help is most useful when the team has not crossed multiple stops before, when the instance has several nodes, or when the window is short. Your own staff remain responsible for the instance after the work ends.
What should we test in the GitLab API and container registry before upgrading?
Test every automation that calls the API or pushes and pulls images, because those clients often break without an obvious error. Build the list from your own inventory: scripts that use personal or project access tokens, CI jobs that push or pull container images, deployment tools that read registry tags, and reporting or ticketing integrations. For each client, run a read and a write against a staging copy on 19.x, compare the responses with the expected output, and confirm that token scopes still grant the access they need. Review the 19.0 release notes for removed or changed endpoints and registry behavior, because this page does not list them. Record each result so the cutover decision has evidence behind it.
How does rollback work if we stop partway through the upgrade?
Rollback depends on the stop you have reached and on the backup you took before it, so treat restore as a rehearsed step. Take a full backup before each required stop, and include the secrets file, because GitLab's backup guidance treats it as part of a complete backup. Confirm in the documentation for each version whether a downgrade is supported, and do not assume one. Keep the previous package versions available, record the database state at each stop, and agree in advance on who decides to roll back and the time by which that decision must be made. Test the restore on a separate host before the change window opens. The backup and restore documentation is the starting point for the procedure.
How do air-gapped or multi-node GitLab instances change the upgrade?
They change the order of work and the packages you must move, so the plan changes more than the commands do. In an air-gapped environment, you must transfer packages and dependencies into the network and rehearse the upgrade offline. GitLab documents offline environments and gives separate guidance for running its security scanners and GitLab Duo Self-Hosted offline, so check those components too. On a multi-node instance, the upgrade follows a set order across load balancers, application nodes, Gitaly and the database, and the zero-downtime procedure moves one minor release at a time. GitLab recommends a high availability strategy for 3,000 or more users, so confirm which topology you run before estimating the window.
What makes a GitLab upgrade longer than expected
The number of required stops is the first driver of duration. An instance that starts on an early 18.x release has to pass through each stop, such as 18.2, 18.5, 18.8 and 18.11, before 19.0, and each hop needs its own backup, post-upgrade checks and time for batched background migrations to reach Finished. Check the current version in the Admin area and map the full path against the GitLab upgrade paths documentation before setting a window. Database size is the second driver. A larger PostgreSQL data set lengthens the backup, the migrations and the restore point you would rely on if a hop fails, so ask for the database size and migration status as part of scoping.
Configuration and topology add the most variation. A heavily customized gitlab.rb file, with custom ports, storage paths, proxy settings or omnibus overrides, has to be reconciled with each release, and every change is a potential source of delay. External PostgreSQL or Redis instances move on their own schedule: PostgreSQL 17 and Redis 7 must be in place before the 19.0 hop, and an external database upgrade is a separate procedure with its own rollback plan. A multi-node topology behind a load balancer adds node ordering and health checks to every stop. The reference architectures recommend high availability for 3,000 or more users, so confirm whether the instance already runs that layout and who owns each component.
Runners and API consumers are often underestimated. A GitLab Runner fleet has to stay aligned with the server on major and minor versions, so a large fleet adds an upgrade cycle of its own. Integrations that call the REST or GraphQL API, along with scripts and deployment tools, need to be tested against 19.0 in staging, because removed or changed fields break silently. Most of this work is one-time: planning, staging rehearsal, integration test updates and the first production window. Recurring costs appear with each later stop, runner maintenance and any support retainer. When requesting a quote, ask for the number of stops, node and database topology, runner count, an inventory of API consumers, backup and rollback responsibilities, and the staging environment the work will use.
Which factors widen or shorten the upgrade scope
This table lists the factors that change how much work a GitLab 18 to 19 upgrade involves, and the direction each one pushes scope. Read it before requesting a quote, because the same target version can mean a short maintenance window on one instance and a multi-stage program on another.
| Driver | Effect on scope | What to confirm before planning |
|---|---|---|
| Installation method | Linux package installs are the most common path and keep bundled PostgreSQL, Redis and Sidekiq under one upgrade procedure. Helm chart, Operator, Docker or source installs add chart or image version mapping and separate component ordering. | Which method you run today and whether your version mapping for it has been checked against the 19.x documentation. |
| Database topology | A bundled PostgreSQL on one node is the simplest case. An external or clustered PostgreSQL, or a Patroni-managed cluster, adds a PostgreSQL 17 upgrade with its own cutover and rollback plan. | Whether PostgreSQL is bundled or external, its current major version, and who owns the cluster change. |
| Redis topology | A bundled Redis or a single external Redis instance is simpler. Redis Sentinel or a separate cache and queue split adds verification of Redis 7 readiness on each node. | Redis deployment layout, current version, and whether Sentinel is in use. |
| Reference architecture size | Smaller single-node or small reference architectures involve fewer components to sequence. Larger deployments with Gitaly Cluster, Praefect, Sidekiq and multiple web nodes need coordinated order and more post-upgrade checks. | The reference architecture you follow and the number of nodes per component. |
| Custom integrations and API consumers | Each CI system, chat hook, script or internal tool that calls the REST or GraphQL API adds test cases. Registry clients and deploy tooling that depend on changed behavior extend the test window. | An inventory of API consumers, webhooks, registry users and scripts, with owners for each. |
| Runner versions | Runners that lag behind the server need alignment work in the same window. Older fleets with legacy executors or retired registration methods add rebuild or re-registration tasks. | Runner versions, executor types and whether any fleet predates the current registration model. |
| Offline or air-gapped constraints | Air-gapped instances need package, container and dependency mirrors refreshed for the target version. Offline scanners and self-hosted AI components require their own update sources. | How packages and images reach the network, and whether scanner databases and models update offline. |
| Edition in use | Free and Premium deployments have a smaller set of features to retest. Ultimate deployments that use security scanning, compliance or Geo add configuration and verification steps per feature. | Current tier, enabled features and whether Geo or scanner policies are in use. |
How to test API, registry and runners before go-live
Run the full test plan on a restored copy of production before any change reaches the live instance, because the database migrations that run during the 18 to 19 path cannot be reversed by simply redeploying the old packages. Build the copy from a fresh backup taken with the gitlab-backup task, restore it onto identical operating system and PostgreSQL 17 infrastructure, and run the upgrade stops there in the same order you plan for production. Start the test with the API. Script regression calls against the endpoints your CI jobs, deployment tools, reporting scripts and chat bots actually use, authenticated with the same token types they use today. Compare status codes and response fields against the 18.x baseline, and record every field that disappears or changes type so you can check it against the GitLab 19 release notes before go-live. Confirm the list of changes with the GitLab documentation for your exact target version, since this guide does not list the removed items.
Next, test the container registry and runners as separate workloads. For the registry, push and pull images from a test project using the same credentials, storage backend and external URL your pipelines use, and confirm that tag listing, manifest pulls and cleanup policies behave as expected. For runners, register a test runner against the upgraded instance using the registration method your fleet will use, then run jobs on every executor type you operate, including Docker and autoscaling executors. Check that the runner version matches the GitLab major and minor version, as GitLab's Runner documentation advises, and that jobs that pull images, read CI variables and reach external services still succeed. Any runner that fails registration on the test copy should be fixed before the production window, not after.
Finish with authentication and recovery checks. Log in through each SSO and LDAP path your users rely on, including group sync and any SCIM provisioning, and confirm that existing sessions, personal access tokens and deploy tokens still work. Then perform a restore verification: restore the backup into an isolated environment, confirm that repositories, registry data, CI variables and the gitlab-secrets.json file are present, and time the restore so you know how long a real rollback would take. Once a migration has run on production, rollback means restoring the database and data from the backup taken before that stop, not reverting packages. That is why each backup taken before a required stop is the rollback anchor, and why you should confirm with your own team how long a restore takes before you accept the risk.
How DeployOpen works on this
DeployOpen is a Chainscore Labs company that plans, implements, hardens, backs up, upgrades and documents self-hosted open-source platforms inside your own infrastructure. For a GitLab 18 to 19 upgrade, we start from your current version, topology and integrations, then write down every stop, prerequisite and test before any change is made.
How we scope
- Inventory your current GitLab version, edition, install method and whether you run a single node or a multi-node deployment
- Map the required upgrade stops, including 18.11, and the order of stops your instance must pass through
- Confirm PostgreSQL 17 and Redis 7 prerequisites, operating system support and the bundled or external database layout
- Record the scope in writing before work starts, since most engagements are fixed-scope with agreed deliverables and timelines
How we build
- Prepare a staging copy of your instance and rehearse each stop, checking background migrations finish before moving on
- Test API clients, CI/CD configuration, container registry settings and removed bundled components against the 19 release notes
- Upgrade PostgreSQL and Redis as separate planned changes, with tested backups taken before each step
- Run GitLab Runner version alignment checks alongside the server upgrade so job execution stays compatible
How we hand over
- Deliver a runbook listing each stop, command, validation check and rollback point for your team to reuse
- Document configuration changes in your gitlab.rb and related files so the upgraded state is reproducible
- Provide test results for API, registry and pipeline checks, with open issues and owners named clearly
- Walk your administrators through the procedure so they can repeat it for future required stops
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after the upgrade is complete
- A retainer can cover monitoring of new GitLab patch and minor releases against your deployment and tests
- Ask us to plan the next required stop, such as the 19.2 or 19.5 stop, as part of the same ongoing arrangement
- Confirm response expectations, service levels and included hours in the written retainer before signing

