When a GitLab Geo secondary helps distributed teams
A GitLab Geo secondary is worth considering when several offices or runner fleets sit far from one self-managed GitLab primary and developers or pipelines notice slow clones and fetches. Geo is documented as a warm-standby secondary for disaster recovery, continuously synchronized in another location, and it is available in the Premium and Ultimate tiers for self-managed GitLab. The same secondary can also serve read traffic from a nearby site, while writes such as pushes, merge requests and issue updates still go to the primary. Treat the read offload as a benefit to verify, not a given: confirm with the GitLab Geo documentation for your exact version which read paths (Git over HTTP and SSH, web views, container and package registry reads, artifacts) are served locally and which are proxied to the primary.
The decision starts with two questions. First, how much of the traffic from each remote site is reads that a local replica can answer, compared with writes that will cross the WAN regardless? Second, do you need the secondary for disaster recovery anyway, which would make the local read benefit a secondary return on the same infrastructure? Answer both with measurements from your current instance, such as clone and fetch timings from each office and the share of CI jobs that run on remote runners. A secondary does not remove the need for backups, so the recovery plan must still include them. Ask any implementation partner to show, in a written scope, which sites get a secondary, which runners attach to which site and how the proxying behavior was checked on your version.
Remote office users versus CI runners
Office engineers spend most of their time browsing projects, cloning repositories, reading diffs and leaving review comments. A Geo secondary at the office can serve the read side of that work from local storage, so clones and page loads stop crossing the WAN for every request. The primary remains the source of truth for anything that changes state.
- Served locally: Clones and fetches for replicated projects, read from the secondary's own storage.
- Still crosses the WAN: Pushes, merge request actions, comments and approvals, which the secondary forwards to the primary.
- Replication lag: Commits pushed in one location may take time to appear at the office, so a developer can see a stale branch right after a colleague pushes.
- Sign-in: Authentication and SSO callbacks depend on the primary, so confirm how login behaves during a WAN outage.
Test a clone of your largest project, a push from the office and a merge request action, and note which requests reach the primary while you watch the replication status.
A runner fleet at a remote site executes jobs that fetch repositories, pull dependencies and upload artifacts. Placing runners near a Geo secondary can shorten the clone step for large repositories, but jobs still depend on the primary to receive work and report results. Confirm the current secondary behavior in the Geo documentation before you size the fleet around local reads.
- Benefits: Repository fetches made by jobs can come from the local secondary, which reduces clone time on large repositories.
- Still crosses the WAN: Job assignment, status updates, log streaming and artifact uploads. Treat these as primary-bound until your version's documentation shows otherwise.
- Version alignment: Keep the Runner major and minor versions aligned with GitLab so the remote fleet moves with each upgrade.
- Caches and registry traffic: Dependency caches, container registry pulls and object storage access need their own network path and are not covered by repository reads.
Test a job that clones your largest repository on the remote network, an artifact upload at a realistic size, and a job run while the WAN link is slow, and record how long each step takes.
Both groups rely on the same secondary, so some checks apply to office users and runners alike. A Geo secondary is useful as a read cache and as a warm standby, but a team should not depend on local reads until the site has been verified against the primary. The GitLab Geo documentation is the reference for current behavior and supported configurations.
- Network ports: Confirm every port required between the primary and secondary in the Geo documentation, then open only those ports in your firewalls and security groups.
- Replication status: Check sync status for repositories and blobs before teams start relying on the local copy, and recheck after large pushes.
- Write paths: List which write requests reach the primary, then test each one with the WAN link deliberately interrupted.
- Recovery role: Treat the secondary as a disaster recovery site as well, and plan promotion and backups separately from read performance.
Record the results in a shared runbook so that office and CI owners know which behaviors were verified and which were assumed.
Geo configuration options and when each fits
This table compares the main Geo layout decisions for distributed teams: where secondaries sit, whether each office gets its own, where runners go and how users reach the instance. Read each row against your office map and CI load, then pick the option whose trade-off you can live with.
| Decision | Option | Trade-off | When it fits |
|---|---|---|---|
| Secondary placement | Secondary in each major office region | More sites to patch, monitor and fail over, but local reads for each office | Several large offices with heavy daily clone, fetch and review traffic |
| Secondary placement | Secondary in a single remote region | Fewer sites to operate, but distant offices still read across the WAN | Most users sit near one location and the rest work mainly in the primary |
| Secondary count | One secondary per site | Each site has local reads and its own disaster recovery target, at higher operating cost | Sites hold independent workloads or have different compliance boundaries |
| Secondary count | Shared secondary for several sites | Lower footprint, but all sites depend on one replica and one network path | Nearby offices share a network and the team accepts a single shared failure point |
| Runner placement | Runners near the Geo secondary | Jobs pull code locally, but runners must reach the primary for job and artifact traffic you confirm in your version | Remote teams whose builds are dominated by repository and dependency fetches |
| Runner placement | Runners near the primary | Simpler network and tighter control, but remote jobs carry WAN latency | Central data center teams, or sites with little build traffic |
| URL strategy | Separate hostnames per site | Clear routing and simple certificates, but users must know which address to use | Small deployments, or teams that prefer explicit site selection |
| URL strategy | Unified URL with location-aware DNS | One address for everyone and automatic routing, but requires DNS and certificate work covered in the sibling topic | Many sites where users should not choose a hostname and the team can run the DNS setup |
Setting up a Geo secondary for a remote site
This sequence takes a remote office or runner location from an unplanned gap to a Geo secondary that serves reads locally and proxies writes to the primary. Each step ends with a check so you know the site is ready before users or runners depend on it.
Confirm tier and matching versions
Confirm that the primary and the planned secondary both run an edition and tier that includes Geo. The GitLab pricing page lists Geo for Premium and Ultimate on self-managed installations, so check the license on the primary before you plan anything else. Record the exact GitLab version on both sites and confirm that they match on major and minor version. Check that the version pair is a supported combination in the GitLab Geo documentation. Done means you have a written version record for both sites and a license that covers Geo.
Prepare the secondary at matching versions
Install the secondary with the same major and minor version as the primary, using the install method your team already runs for the primary. Build the secondary as a separate GitLab instance with its own database, Gitaly storage and object storage settings, sized for the users and runners it will serve. Confirm that the secondary's
external_urlis set to its own hostname and that it is not yet serving as a primary. Done means the secondary starts cleanly and reports the same version as the primary.Configure the primary as the Geo primary
On the primary, enable Geo and mark it as the primary site in the Geo settings. Confirm that the primary's database and object storage are reachable from the network path the secondary will use, and that the backup prerequisites are in place before replication starts, as covered in the backup section of this guide. Make sure the primary's
gitlab-secrets.jsonis available for copying to the secondary, since the secondary must share it. Done means the primary shows itself as the Geo primary site in the admin area and the secrets file is confirmed as in place.Add the secondary and open the required ports
From the primary, add the secondary site with its public or internal URL and complete the setup commands on the secondary using the database and replication settings from the Geo documentation. Open the network ports the replication services need between the two sites, and allow the secondary to reach the primary's PostgreSQL and HTTPS endpoints. Confirm each port with a connectivity test from both directions before running the setup. Done means the secondary appears in the Geo site list with a status that is not failed.
Verify replication and sync status
Check the Geo site status on the primary and on the secondary. Confirm that database replication, repository replication and file replication show as healthy, and that the replication lag is decreasing as the initial sync runs. Run the Geo health checks in the GitLab documentation and review any failed verification counts on repositories and blobs. Investigate any failed item before you move on, since a secondary with unverified data should not serve users. Done means the sync status is complete and verification shows no unresolved failures.
Point runners and users at the right hostname
Decide which hostname each group uses. Remote users should open the secondary's URL for reads, while write operations are proxied to the primary, so confirm that the secondary's proxy behavior matches what your users expect. Register runners at the primary hostname for job registration and confirm which artifact and cache paths they reach locally. Test a clone from the remote site, a push that is proxied to the primary and a pipeline job that starts on a runner at that site. Done means a test user at the remote site can clone, push and run a job without errors.
Which network ports and paths to open between sites
Plan the firewall rules for a Geo secondary as four separate traffic categories, because each one has a different source, destination and failure mode: user traffic from remote offices to the local secondary, traffic from the secondary back to the primary, database and replication connectivity, and runner traffic to whichever instance serves the job. Start from the Geo documentation for your exact GitLab version rather than from a port list copied from another project, and record each rule against the category it serves. This section does not state port numbers; confirm the complete list in the GitLab Geo documentation before you open anything.
For user access, the office network needs HTTPS to the secondary for web and Git over HTTPS. If your engineers use SSH for Git, decide whether the secondary will answer SSH locally or whether SSH will be proxied to the primary, and open the matching path only. Runners need a clear rule for where they fetch repositories and register with the coordinator. Confirm with the vendor documentation which requests a secondary proxies to the primary, since writes and some API calls always go upstream, and make sure your proxy and load balancer rules match that behavior.
The secondary must reach the primary on the internal endpoints that Geo uses for synchronization and for its database and Redis connections, so the path between sites must be encrypted and restricted to those source addresses. Ask your team to test with the rules applied, not only with them documented: run a Geo health check, push and pull from a remote office, and trigger a replication cycle while logging dropped packets. Treat any port you cannot tie to a documented function as a finding to resolve before cutover. Keep the rule set under change control, because a later GitLab upgrade can add or change required paths.
Security and operations for cross-site Geo
A Geo secondary holds a copy of your most sensitive GitLab data, and it sits in an office with its own users, runners and network. The cards below cover what replicates, where secrets must match, how access and transport are protected, and how to watch replication and backups at the remote site.
Replicated data and the secrets file
A secondary replicates repositories, database content and most uploads, so it holds the same sensitive material as the primary. The secondary must use the same gitlab-secrets.json as the primary, because encrypted values such as two-factor secrets and CI variables cannot be read without it. Confirm the file is copied through a controlled channel and that its permissions match the primary's.
Access control on the secondary
Users who read from a local secondary still pass through GitLab's authentication and project permissions, but the local site becomes another place where administrators can see the data. Decide who holds admin rights on each secondary, whether those accounts use the same identity provider settings as the primary, and how revoked users are removed from the replica's sessions. Test a removed user's read access at the remote site.
Encrypted replication links
Replication traffic between the primary and each secondary crosses the public or private network between sites, so it must be encrypted in transit. Confirm which certificates the secondary trusts, how they renew, and whether the replication endpoints are reachable only from the other Geo site. Check the same settings on the proxied HTTPS path that remote users use to reach the primary.
Runner tokens and isolation at remote sites
Runners at a remote site register with GitLab using tokens, and a runner that can reach the primary can execute jobs for any project it is allowed to serve. Use project or group scoped runners for the remote team, rotate registration tokens after each rollout, and keep runner hosts on a separate network segment from office workstations. Confirm which executor each runner uses and whether job containers can reach internal services.
Monitoring replication lag
A secondary that falls behind serves stale data, and a planned or unplanned failover then loses the changes that never arrived. Watch replication status and lag for repositories, uploads and the database on each secondary, and set alerts before lag grows into a backlog. Include the Geo health indicators in your routine checks, and record a baseline lag figure during normal working hours.
Confirming the secondary's own backups
Geo replicates changes but does not replace backups, because deleted or corrupted data is copied to the secondary too. Ask whether the secondary runs its own backup schedule, where those archives are stored, and whether a restore has been tested on that site. Confirm that the secondary's secrets file is included in its backup set, since restores need it alongside the archive.
Questions buyers ask about GitLab Geo for remote teams
Which GitLab tiers include Geo, and what does it add to the bill?
Geo is available on the Premium and Ultimate tiers for self-managed GitLab, while the Free tier does not include it. The GitLab pricing page lists Premium at 29 US dollars per user per month billed annually and Ultimate as custom priced, so the licence line depends on your user count and the tier you choose. Geo itself adds infrastructure cost on top: a second site with its own application nodes, storage, database and replication traffic between sites. Those costs recur monthly, while design and build work is one-time. Ask any quote to split licence, secondary infrastructure, network links and services so you can see what scales with users and what scales with repository size.
How long does it take to stand up a Geo secondary for a remote office?
The duration depends on the size of the primary, the amount of data to replicate and the quality of the link between sites, so no single figure applies. The initial sync copies repositories, uploads, LFS objects and other data, and that can take far longer than the configuration itself on a large instance. Other drivers include the reference architecture you run at each site, whether the secondary has its own object storage, how much of the network path is already open and how many test cycles the team needs before cut-over. Ask for a timeline tied to your measured data volume and link bandwidth, and confirm it against the current GitLab Geo documentation.
What does our team need to provide before a Geo project starts?
Plan to provide people and environment access before any build begins. You need named owners for GitLab administration, network and firewall changes, DNS, certificates, and the database and object storage at each site. The team also needs a current, tested backup of the primary and access to the gitlab-secrets.json file, because a secondary must share the same secrets as the primary. Expect to supply measured repository and storage sizes, user locations, the expected write traffic and the maintenance windows you accept for cut-over testing. Agree on these inputs in the written scope so that the timeline reflects real constraints.
Can an internal platform team run Geo without outside help?
An experienced GitLab administration team can run Geo, but it is a multi-site distributed system and failures are harder to diagnose than on a single instance. The team needs skill in PostgreSQL replication, object storage, DNS, certificates and the Geo health checks, and it needs a rehearsed failover runbook. Consider whether the people who would respond at 2 a.m. have practised a switchover and a re-sync. A common middle path is an internal team that owns daily operations, with an external partner for design, the first build, the failover test and the upgrade procedure. Decide this on the skills you have today, not on the tool alone.
How is Geo different from placing CI runners close to remote teams?
Geo and runner placement solve different problems. A Geo secondary replicates GitLab data, so remote users can read repositories and related content from a local site, and it serves as a warm standby for disaster recovery. A GitLab Runner is the application that executes CI/CD jobs, and you can place runners near remote offices or build farms without any Geo site. Runners connect to the GitLab instance to receive jobs and report results, so they still depend on the primary for coordination. If your pain is slow CI job startup or artifact transfer, start with runner placement and its executor choice. If your pain is slow repository access for people in another region, or you need a standby, evaluate Geo.
How do we coordinate GitLab upgrades across the primary and secondary sites?
Upgrade the primary and every secondary to the same GitLab version, and plan the sequence before the first upgrade. 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, so a site that skips a stop cannot be brought forward in one step. The maintenance policy backports bug fixes only to the current stable release, and security fixes to the previous two monthly releases too, so schedule patch releases promptly on every site. Keep GitLab Runner major and minor versions aligned with the instance, and rehearse each upgrade on a non-production copy. Ask your partner for a written upgrade runbook that names the stop versions and the order of sites.
Does a Geo secondary change where our source code and CI data live?
Geo replicates data to the secondary so the copy is available for reads and for failover, but the primary remains the system of record for writes. Remote users see the replicated content locally, while actions that change data are proxied back to the primary. Confirm with GitLab exactly which operations are served locally and which are proxied for your version, because the list changes between releases. For data residency, a secondary is still a full copy of your repositories and metadata, so it falls under the same controls as the primary. Include both sites in your access reviews, backup scope and encryption requirements.
Deciding between Geo, runner placement and a second instance
A Geo secondary is the right tool when the problem is distance between people and the primary, and when the business also wants a warm-standby site for disaster recovery. A Geo secondary replicates the instance continuously to another site, so a remote office can read repositories and the UI from nearby hardware while writes still go to the primary. That benefit is real only if most of the team's daily reads come from the remote site and the link to the primary is the bottleneck. Before committing, confirm which tier the organization needs, since GitLab documents Geo for Premium and Ultimate self-managed installations, and map which parts of the workflow your teams actually feel as slow. Pushes, merge request writes and most API calls still travel to the primary, so latency there will not disappear.
Often the simpler fix is not Geo at all. If the slow step is CI, placing runners close to the artifacts, container registries and deployment targets they use may solve the problem without replicating the whole instance. Runners are a separate application that connects outward to the instance, so a runner in a remote office can pick up jobs from a primary in another region, provided the network path and the runner's registration are sound. A second, separate GitLab instance is the right answer when the sites must be governed independently, when they have different identity providers or compliance boundaries, or when there is no need for a shared project namespace. Each option trades operational work for latency, and a written comparison of these three paths should come before any architecture decision.
Geo does not remove the need for backups. Replication copies changes as they happen, so a bad deletion, a corrupted database or a ransomware event on the primary can replicate to the secondary within the same window. Plan backup archives for the primary and the secondary, keep the gitlab-secrets.json file with them, and test restores on a schedule. Ask any partner to show how the recovery approach combines Geo with backups and which failover runbook covers your instance size and data loss tolerance. Those answers, not the presence of a secondary, determine whether the design holds up under an incident.
How DeployOpen scopes and delivers a Geo rollout
The sequence turns a distributed-team question into a written scope, a tested secondary site inside your infrastructure and a handover your own engineers can operate. Each step closes with a named output so you can check progress before the next one starts.
Inventory sites, users and runners
DeployOpen's engineers list every site that will use a local read cache, the number and location of users at each one, the runners that should execute jobs close to those teams and the primary instance's version, edition and topology. They also record which traffic is latency sensitive, such as large clones, and which must always reach the primary, such as writes. The output is a site and runner inventory that you review and sign off, which becomes the basis for the written scope.
Agree scope and deliverables in writing
Both parties agree the written scope before any build work starts. It names the Geo sites, the edition and tier required (Geo is available in Premium and Ultimate for self-managed GitLab), the network ports and routes to be opened between sites, the runner placements, the acceptance tests and the timeline. Pricing follows from this document, so you can compare it against an internal estimate on equal terms. The output is a signed scope document with explicit exclusions.
Confirm network paths and access rules
DeployOpen's engineers work with your network team to map the ports and paths between the primary, each secondary and the runners, including the database and Redis replication traffic that Geo requires. They confirm firewall rules, DNS names, certificate ownership and which outbound services each site may reach, including any offline or air-gapped constraints. The output is an approved connectivity diagram and change requests your change board can review.
Build the secondary in your environment
The secondary is installed in the cloud account, data center or network you control, using the install method and reference architecture chosen during scoping. DeployOpen configures the secondary as a read cache, aligns its GitLab version with the primary, and places runners in the sites that need them. Work is carried out in your environment under your access controls, and each configuration change is recorded. The output is a running secondary that is registered with the primary and ready for testing.
Test replication and proxied requests
The team checks that repositories and other replicated data reach the secondary, that reads are served locally and that writes are proxied to the primary as documented. They measure replication lag under normal load, test runner job execution from each site and confirm that failures in the link are visible to operators. Test results are logged against the acceptance criteria in the scope. The output is a test report that shows which criteria passed, failed or were deferred, with agreed remediation for any gaps.
Document operations and hand over
DeployOpen prepares runbooks for health checks, monitoring of replication, adding and removing runners, and the procedures your team will use during an incident or maintenance. Your engineers take part in a supervised run of these procedures so that knowledge moves to your staff before the engagement closes. The output is a handover package and a signed acceptance record that matches the agreed deliverables.
Continue support through optional retainers
After handover, you can choose a retainer for ongoing support, upgrades and continuous testing rather than relying solely on your own team. Upgrade planning follows the required upgrade stops, so the retainer scope should state how Geo sites are upgraded in the correct order. Retainer terms, response expectations and included activities are written down separately from the build scope. The output is an agreed support schedule that you can adjust as your teams and sites change.

