[{"data":1,"prerenderedAt":1163},["ShallowReactive",2],{"/blog/geo-is-available-on-staging-for-gitlab-com":3,"navigation-en-us":363,"banner-en-us":791,"footer-en-us":801,"blog-post-authors-en-us-Fabian Zimmer|Douglas Alexandre":1046,"blog-related-posts-en-us-geo-is-available-on-staging-for-gitlab-com":1073,"blog-promotions-en-us":1099,"next-steps-en-us":1153},{"id":4,"title":5,"authors":6,"body":9,"category":341,"date":342,"description":343,"extension":344,"externalUrl":345,"faq":345,"featured":346,"heroImage":347,"meta":348,"navigation":349,"path":350,"seo":351,"slug":355,"stem":356,"tags":357,"template":361,"updatedDate":345,"__hash__":362},"blogPosts/en-us/blog/geo-is-available-on-staging-for-gitlab-com.md","Why we enabled Geo on the staging environment for GitLab.com",[7,8],"Fabian Zimmer","Douglas Alexandre",{"type":10,"value":11,"toc":327},"minimark",[12,23,32,35,38,43,51,59,64,73,76,80,83,87,90,99,106,126,141,144,154,174,177,198,211,219,223,244,248,251,254,268,272,292,296,310,313],[13,14,15,16,22],"p",{},"We're testing Geo at scale on GitLab.com – our largest installation of GitLab – because we believe the best way to guarantee that Geo works as expected is to ",[17,18,21],"a",{"href":19,"rel":20},"https://handbook.gitlab.com/handbook/product/product-processes/#dogfood-everything",[],"use it ourselves",".",[13,24,25,26,31],{},"Geo is GitLab's ",[17,27,30],{"href":28,"rel":29},"https://docs.gitlab.com/administration/geo/",[],"solution for distributed teams",". We want teams all over the world to have a great user experience - independent of how far away users are from their primary GitLab installation. To accomplish this goal, read-only Geo nodes can be created across the world in close geographical proximity to your teams. These Geo nodes replicate important data, such as projects or LFS files, from the primary GitLab instance and thereby make the data available to users. Geo can also be used as part of a disaster recovery strategy because it adds data redundancy. Geo nodes follow the primary installation closely and allow customers to failover to this node in case the primary node becomes unavailable.",[13,33,34],{},"Many of GitLab's customers use Geo on self-managed installations that serve hundreds to thousands of users. Geo is a critical component of GitLab installations and our customers expect Geo to work at any scale. We are testing Geo at scale on our GitLab.com installation because if it works for us, chances are it will work for our worldwide group of users too.",[13,36,37],{},"In this blog post, we'll explain why and how we chose to enable GitLab Geo on our pre-production environment (from now on referred to as \"staging\"), the challenges we encountered, some of the immediate benefits to our customers, and what will be next.",[39,40,42],"h2",{"id":41},"why-do-we-need-to-use-geo-at-gitlab","Why do we need to use Geo at GitLab?",[13,44,45,46,50],{},"In order to build the best product possible, we believe it is imperative to ",[17,47,49],{"href":19,"rel":48},[],"use GitLab ourselves",". Many of our Geo customers have thousands of users actively using GitLab and a major challenge for the team was to test and validate new Geo functionality at scale. Enabling Geo on the GitLab.com staging environment makes this task a lot easier.",[13,52,53,54,58],{},"We also used Geo to ",[17,55,57],{"href":56},"/blog/moving-to-gcp/","migrate GitLab.com from Microsoft Azure to Google Cloud in 2018",", which allowed us to improve the product by identifying bottlenecks. In the last two years, GitLab has grown dramatically and in order to push Geo forward, we need to enable it (again).",[60,61,63],"h3",{"id":62},"test-geo-at-scale","Test Geo at scale",[13,65,66,67,72],{},"When the team decides to add new functionalities to Geo, for example ",[17,68,71],{"href":69,"rel":70},"https://gitlab.com/groups/gitlab-org/-/epics/2346",[],"package repository replication",", we had to ensure that the feature's performance is as expected. Having Geo available on staging allows us to deploy these changes behind a feature flag first and evaluate the performance before shipping the feature to customers. This is especially relevant to some of Geo's PostgreSQL database queries. On a small test deployment, things may look fine, but at scale these queries can time out, resulting in replication issues.",[13,74,75],{},"We also deploy code to our staging environment twice a week, which means that any regressions surface before a new packaged release.",[60,77,79],{"id":78},"prove-that-geo-can-be-deployed-as-part-of-our-production-infrastructure","Prove that Geo can be deployed as part of our production infrastructure",[13,81,82],{},"A large amount of automation is required to run GitLab.com with millions of users, and our SRE team is constantly improving how we run GitLab.com. The first step bringing Geo into our production environment is to deploy Geo as a part of our staging environment. Without the right monitoring, runbooks, and processes in place, it would not be possible to move Geo into production where it could be used to enable geo-replication and/or as part of our disaster recovery strategy.",[39,84,86],{"id":85},"setting-up-geo-on-staging","Setting up Geo on staging",[13,88,89],{},"Setting up Geo on staging had some unique challenges, you can get a detailed overview in our Geo on staging documentation.",[13,91,92,93,98],{},"In order to deploy Geo, we opted for a minimally viable approach that is sufficient for a first iteration. Geo is currently deployed as a single all-in-one box, not yet as a ",[17,94,97],{"href":95,"rel":96},"https://docs.gitlab.com/administration/geo/replication/multiple_servers/",[],"Geo high-availability configuration",". Geo deploys happen automatically via Chef, similar to any other part of the infrastructure.",[13,100,101],{},[102,103],"img",{"alt":104,"src":105},"Geo staging Diagram","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398302/blog/Content%20Images/geo-on-staging/geo_staging_diagram.png",[13,107,108,109,114,115,119,120,125],{},"We currently replicate only a subset of data using ",[17,110,113],{"href":111,"rel":112},"https://docs.gitlab.com/administration/geo/replication/configuration/#selective-synchronization",[],"Geo's selective synchronization feature",", which also allows us to dogfood this feature. Selective synchronization uses a number of complex database queries and this helps us validate those at scale. We chose to replicate the ",[116,117,118],"code",{},"gitlab-org"," group, which contains mostly of GitLab's projects (including ",[17,121,124],{"href":122,"rel":123},"https://gitlab.com/gitlab-org/gitlab",[],"GitLab"," itself).",[13,127,128,129,134,135,140],{},"We also needed to configure Geo to use the same logical ",[17,130,133],{"href":131,"rel":132},"https://docs.gitlab.com/administration/repository_storage_paths/",[],"Gitaly shards"," on the secondary compared to the primary node. We'll ",[17,136,139],{"href":137,"rel":138},"https://gitlab.com/gitlab-org/gitlab/-/issues/213840",[],"improve our Geo documentation"," to ensure it is clear when this is required.",[13,142,143],{},"A logical Gitaly shard is an entry in the GitLab configuration file that points to a path on the file system and a Gitaly address:",[145,146,152],"pre",{"className":147,"code":149,"language":150,"meta":151},[148],"language-text","\"git_data_dirs\": {\n  \"default\": {\n    \"path\": \"/var/opt/gitlab/git-data-file01\",\n    \"gitaly_address\": \"unix:/var/opt/gitlab/gitaly/gitaly.socket\"\n  }\n}\n","text","",[116,153,149],{"__ignoreMap":151},[13,155,156,157,160,161,164,165,167,168,171,172,22],{},"In the example above, we have only one logical shard identified by the key ",[116,158,159],{},"default",", but we could have as many as needed.\nEvery project on GitLab is associated with a logical Gitaly shard, which means that we know where all relevant data (repositories, uploads, etc.) is stored. A project ",[116,162,163],{},"example"," that is associated with the logical Gitaly shard ",[116,166,159],{},", would therefore be stored at ",[116,169,170],{},"/var/opt/gitlab/git-data-file01"," and the Gitaly server would be available at ",[116,173,170],{},[13,175,176],{},"This information is stored in the PostgreSQL database and in order for Geo to replicate projects successfully we needed to create the same Gitaly shard layout. On the Geo secondary node, we are using only one physical shard to store the data for all projects. To allow it to replicate any project from the primary node, we had to point all the logical Gitaly shards to the same physical shard on the secondary node.",[13,178,179,180,185,186,191,192,197],{},"Geo on staging is configured to use ",[17,181,184],{"href":182,"rel":183},"https://www.postgresql.org/docs/current/warm-standby.html#CASCADING-REPLICATION",[],"cascading streaming replication",", which allows one standby node in the staging ",[17,187,190],{"href":188,"rel":189},"https://github.com/zalando/patroni",[],"Patroni cluster"," to act as relay and stream write-ahead logs (WAL) to the Geo secondary. This setup also has the advantage that Geo can't put an additional load onto the primary database node and we are also not using physical replication slots to further reduce the load. ",[17,193,196],{"href":194,"rel":195},"https://gitlab.com/groups/gitlab-org/-/epics/2588",[],"Patroni will likely be supported in Omnibus packages"," and we will review these settings to allow our customers to benefit from this setup.",[13,199,200,201,204,205,210],{},"PostgreSQL will automatically fall back on its ",[116,202,203],{},"restore_command"," to pull archived WAL segments using ",[17,206,209],{"href":207,"rel":208},"https://github.com/wal-e/wal-e",[],"wal-e",", if it cannot retrieve the segment by streaming replication. This can happen after a failover, or if the replication target has deleted the relevant segment if Geo is lagging behind it.",[13,212,213,214,22],{},"In the future, we will use this to experiment with ",[17,215,218],{"href":216,"rel":217},"https://gitlab.com/groups/gitlab-org/-/epics/2536",[],"high-availability configurations of PostgreSQL on a secondary Geo node",[39,220,222],{"id":221},"what-we-learned-and-how-we-can-improve","What we learned and how we can improve",[13,224,225,226,231,232,237,238,243],{},"We opened ",[17,227,230],{"href":228,"rel":229},"https://gitlab.com/groups/gitlab-org/-/epics/1908",[],"23 issues before successfully rolling out Geo on our staging environment"," - this is too many. We know that installing and configuring Geo in complex environments is time-consuming and error-prone, and is an area where we can improve. The current process for a self-managed installation requires ",[17,233,236],{"href":234,"rel":235},"https://gitlab.com/gitlab-org/gitlab-design/issues/731",[],"more than 70 individual steps"," - this is too much. ",[17,239,242],{"href":240,"rel":241},"https://gitlab.com/groups/gitlab-org/-/epics/1465",[],"Geo should be simple to install"," and we aim to reduce the number of steps to below 10. Using Geo ourselves really underscored the importance of improvements in this area.",[60,245,247],{"id":246},"some-geo-postgresql-queries-dont-perform-well","Some Geo PostgreSQL queries don't perform well",[13,249,250],{},"Geo uses PostgreSQL Foreign Data Wrappers (FDW) to perform some cross-database queries between the secondary replica and the tracking database. FDW queries are quite elegant but have lead to some issues in the past. Specifically, staging is still running PostgreSQL 9.6, and Geo benefits from some FDW improvements available only in PostgreSQL 10 and later, such as join push-down and aggregate push-down.",[13,252,253],{},"While enabling Geo on staging, some FDW queries timed out during the backfill phase. Until staging is being upgraded to a newer version of PostgreSQL, increasing the statement timeout to 20 minutes on the Geo secondary node was sufficient to allow us to proceed with the backfill.",[13,255,256,257,262,263,22],{},"As a direct consequence of enabling GitLab on staging, we are working to ",[17,258,261],{"href":259,"rel":260},"https://gitlab.com/groups/gitlab-org/-/epics/2851",[],"improve Geo scalability by simplifying backfill operations",", eliminating these cross-database queries, and removing the FDW requirement. We also plan to ",[17,264,267],{"href":265,"rel":266},"https://gitlab.com/groups/gitlab-org/-/epics/2414",[],"upgrade to PostgreSQL 11 in GitLab 13.0",[60,269,271],{"id":270},"bug-fixes","Bug fixes",[13,273,274,275,280,281,286,287,22],{},"We've also discovered and fixed a number of bugs in the process, such as ",[17,276,279],{"href":277,"rel":278},"https://gitlab.com/gitlab-org/gitlab/-/issues/209752",[],"failing to synchronize uploads with missing mount points",", ",[17,282,285],{"href":283,"rel":284},"https://gitlab.com/gitlab-org/gitlab/-/issues/210589",[],"invalid ActiveRecord operations",", and ",[17,288,291],{"href":289,"rel":290},"https://gitlab.com/gitlab-org/gitlab/-/issues/207808",[],"excessively re-synchronizing files in some situations",[39,293,295],{"id":294},"whats-next","What's next?",[13,297,298,299,304,305,309],{},"We are already providing value to our customers by enabling Geo on staging because the Geo team can test and validate Geo at scale at lot easier. Next up is enabling ",[17,300,303],{"href":301,"rel":302},"https://gitlab.com/gitlab-org/quality/team-tasks/issues/385",[],"automatic runs of our end-to-end test on staging",", which would reduce the manual testing burden even further. There are also some other improvements, such as ",[17,306,308],{"href":216,"rel":307},[],"enabling high-availability configurations of PostgreSQL using Patroni on Geo nodes"," that we would like to test on staging.",[13,311,312],{},"Even though enabling Geo on staging is already very useful, it is just a step forward to rolling out Geo on GitLab.com in production. We are currently evaluating the business case for enabling Geo on GitLab.com as part of our disaster recovery strategy and for geo replication.",[13,314,315,316,321,322],{},"Cover image by ",[17,317,320],{"href":318,"rel":319},"https://unsplash.com/photos/4qk3nQI3WHY",[],"Donald Giannatti"," on ",[17,323,326],{"href":324,"rel":325},"https://www.unsplash.com",[],"Unsplash",{"title":151,"searchDepth":328,"depth":328,"links":329},2,[330,335,336,340],{"id":41,"depth":328,"text":42,"children":331},[332,334],{"id":62,"depth":333,"text":63},3,{"id":78,"depth":333,"text":79},{"id":85,"depth":328,"text":86},{"id":221,"depth":328,"text":222,"children":337},[338,339],{"id":246,"depth":333,"text":247},{"id":270,"depth":333,"text":271},{"id":294,"depth":328,"text":295},"engineering","2020-04-16","Geo is GitLab's solution for distributed teams and now we can validate and test it at scale.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749669656/Blog/Hero%20Images/donald-giannatti-4qk3nQI3WHY-unsplash-small.jpg",{},true,"/en-us/blog/geo-is-available-on-staging-for-gitlab-com",{"title":5,"description":343,"ogTitle":5,"ogDescription":343,"noIndex":346,"ogImage":347,"ogUrl":352,"ogSiteName":353,"ogType":354,"canonicalUrls":352},"https://about.gitlab.com/blog/geo-is-available-on-staging-for-gitlab-com","https://about.gitlab.com","article","geo-is-available-on-staging-for-gitlab-com","en-us/blog/geo-is-available-on-staging-for-gitlab-com",[358,359,360],"features","inside GitLab","google","BlogPost","uX-aXpjjS5Blf5WAdVAjGr7hfbXIQAKyT9XeEmkPgqc",{"logo":364,"freeTrial":369,"sales":374,"login":379,"items":384,"search":711,"minimal":742,"duo":761,"switchNav":770,"pricingDeployment":781},{"config":365},{"href":366,"dataGaName":367,"dataGaLocation":368},"/","gitlab logo","header",{"text":370,"config":371},"Get free trial",{"href":372,"dataGaName":373,"dataGaLocation":368},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":375,"config":376},"Request a demo",{"href":377,"dataGaName":378,"dataGaLocation":368},"/sales/?contact-topic=request-demo","sales",{"text":380,"config":381},"Sign in",{"href":382,"dataGaName":383,"dataGaLocation":368},"https://gitlab.com/users/sign_in/","sign in",[385,414,514,519,633,689],{"text":386,"config":387,"menu":389},"Platform",{"dataNavLevelOne":388},"platform",{"type":390,"columns":391},"cards",[392,398,406],{"title":386,"description":393,"link":394},"The intelligent orchestration platform for DevSecOps",{"text":395,"config":396},"Explore our Platform",{"href":397,"dataGaName":388,"dataGaLocation":368},"/platform/",{"title":399,"description":400,"link":401},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":402,"config":403},"Meet GitLab Duo",{"href":404,"dataGaName":405,"dataGaLocation":368},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":407,"description":408,"link":409},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":410,"config":411},"Learn more",{"href":412,"dataGaName":413,"dataGaLocation":368},"/why-gitlab/","why gitlab",{"text":415,"left":349,"config":416,"menu":418},"Product",{"dataNavLevelOne":417},"solutions",{"type":419,"link":420,"columns":424,"feature":493},"lists",{"text":421,"config":422},"View all Solutions",{"href":423,"dataGaName":417,"dataGaLocation":368},"/solutions/",[425,449,472],{"title":426,"description":427,"link":428,"items":433},"Automation","CI/CD and automation to accelerate deployment",{"config":429},{"icon":430,"href":431,"dataGaName":432,"dataGaLocation":368},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[434,438,441,445],{"text":435,"config":436},"CI/CD",{"href":437,"dataGaLocation":368,"dataGaName":435},"/solutions/continuous-integration/",{"text":399,"config":439},{"href":404,"dataGaLocation":368,"dataGaName":440},"gitlab duo agent platform - product menu",{"text":442,"config":443},"Source Code Management",{"href":444,"dataGaLocation":368,"dataGaName":442},"/solutions/source-code-management/",{"text":446,"config":447},"Automated Software Delivery",{"href":431,"dataGaLocation":368,"dataGaName":448},"Automated software delivery",{"title":450,"description":451,"link":452,"items":457},"Security","Deliver code faster without compromising security",{"config":453},{"href":454,"dataGaName":455,"dataGaLocation":368,"icon":456},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[458,462,467],{"text":459,"config":460},"Application Security Testing",{"href":454,"dataGaName":461,"dataGaLocation":368},"Application security testing",{"text":463,"config":464},"Software Supply Chain Security",{"href":465,"dataGaLocation":368,"dataGaName":466},"/solutions/supply-chain/","Software supply chain security",{"text":468,"config":469},"Software Compliance",{"href":470,"dataGaName":471,"dataGaLocation":368},"/solutions/software-compliance/","software compliance",{"title":473,"link":474,"items":479},"Measurement",{"config":475},{"icon":476,"href":477,"dataGaName":478,"dataGaLocation":368},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[480,484,488],{"text":481,"config":482},"Visibility & Measurement",{"href":477,"dataGaLocation":368,"dataGaName":483},"Visibility and Measurement",{"text":485,"config":486},"Value Stream Management",{"href":487,"dataGaLocation":368,"dataGaName":485},"/solutions/value-stream-management/",{"text":489,"config":490},"Analytics & Insights",{"href":491,"dataGaLocation":368,"dataGaName":492},"/solutions/analytics-and-insights/","Analytics and insights",{"title":494,"type":419,"items":495},"GitLab for",[496,502,508],{"text":497,"config":498},"Enterprise",{"icon":499,"href":500,"dataGaLocation":368,"dataGaName":501},"Building","/enterprise/","enterprise",{"text":503,"config":504},"Small Business",{"icon":505,"href":506,"dataGaLocation":368,"dataGaName":507},"Work","/small-business/","small business",{"text":509,"config":510},"Public Sector",{"icon":511,"href":512,"dataGaLocation":368,"dataGaName":513},"Organization","/solutions/public-sector/","public sector",{"text":515,"config":516},"Pricing",{"href":517,"dataGaName":518,"dataGaLocation":368,"dataNavLevelOne":518},"/pricing/","pricing",{"text":520,"config":521,"menu":523},"Resources",{"dataNavLevelOne":522},"resources",{"type":419,"link":524,"columns":528,"feature":622},{"text":525,"config":526},"View all resources",{"href":527,"dataGaName":522,"dataGaLocation":368},"/resources/",[529,562,589],{"title":530,"items":531},"Getting started",[532,537,542,547,552,557],{"text":533,"config":534},"Install",{"href":535,"dataGaName":536,"dataGaLocation":368},"/install/","install",{"text":538,"config":539},"Quick start guides",{"href":540,"dataGaName":541,"dataGaLocation":368},"/get-started/","quick setup checklists",{"text":543,"config":544},"Learn",{"href":545,"dataGaLocation":368,"dataGaName":546},"https://university.gitlab.com/","learn",{"text":548,"config":549},"Product documentation",{"href":550,"dataGaName":551,"dataGaLocation":368},"https://docs.gitlab.com/","product documentation",{"text":553,"config":554},"Best practice videos",{"href":555,"dataGaName":556,"dataGaLocation":368},"/getting-started-videos/","best practice videos",{"text":558,"config":559},"Integrations",{"href":560,"dataGaName":561,"dataGaLocation":368},"/integrations/","integrations",{"title":563,"items":564},"Discover",[565,570,575,580,584],{"text":566,"config":567},"Customer success stories",{"href":568,"dataGaName":569,"dataGaLocation":368},"/customers/","customer success stories",{"text":571,"config":572},"Blog",{"href":573,"dataGaName":574,"dataGaLocation":368},"/blog/","blog",{"text":576,"config":577},"Demo Hub",{"href":578,"dataGaName":579,"dataGaLocation":368},"/demo-hub/","demo hub",{"text":581,"config":582},"The Source",{"href":583,"dataGaName":574,"dataGaLocation":368},"/the-source/",{"text":585,"config":586},"Remote",{"href":587,"dataGaName":588,"dataGaLocation":368},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":590,"items":591},"Connect",[592,597,602,607,612,617],{"text":593,"config":594},"GitLab Services",{"href":595,"dataGaName":596,"dataGaLocation":368},"/services/","services",{"text":598,"config":599},"Contribute",{"href":600,"dataGaName":601,"dataGaLocation":368},"https://contributors.gitlab.com","contribute",{"text":603,"config":604},"Community",{"href":605,"dataGaName":606,"dataGaLocation":368},"/community/","community",{"text":608,"config":609},"Forum",{"href":610,"dataGaName":611,"dataGaLocation":368},"https://forum.gitlab.com/","forum",{"text":613,"config":614},"Events",{"href":615,"dataGaName":616,"dataGaLocation":368},"/events/","events",{"text":618,"config":619},"Partners",{"href":620,"dataGaName":621,"dataGaLocation":368},"/partners/","partners",{"config":623,"title":626,"text":627,"link":628},{"background":624,"textColor":625},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":629,"config":630},"Read the latest",{"href":631,"dataGaName":632,"dataGaLocation":368},"/whats-new/","whats new",{"text":634,"config":635,"menu":637},"Company",{"dataNavLevelOne":636},"company",{"type":419,"columns":638},[639],{"items":640},[641,646,652,654,659,664,669,674,679,684],{"text":642,"config":643},"About",{"href":644,"dataGaName":645,"dataGaLocation":368},"/company/","about",{"text":647,"config":648,"footerGa":651},"Jobs",{"href":649,"dataGaName":650,"dataGaLocation":368},"/jobs/","jobs",{"dataGaName":650},{"text":613,"config":653},{"href":615,"dataGaName":616,"dataGaLocation":368},{"text":655,"config":656},"Leadership",{"href":657,"dataGaName":658,"dataGaLocation":368},"/company/team/e-group/","leadership",{"text":660,"config":661},"Handbook",{"href":662,"dataGaName":663,"dataGaLocation":368},"https://handbook.gitlab.com/","handbook",{"text":665,"config":666},"Investor relations",{"href":667,"dataGaName":668,"dataGaLocation":368},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":670,"config":671},"Trust Center",{"href":672,"dataGaName":673,"dataGaLocation":368},"/security/","trust center",{"text":675,"config":676},"AI Transparency Center",{"href":677,"dataGaName":678,"dataGaLocation":368},"/ai-transparency-center/","ai transparency center",{"text":680,"config":681},"Newsletter",{"href":682,"dataGaName":683,"dataGaLocation":368},"/company/contact/#contact-forms","newsletter",{"text":685,"config":686},"Press",{"href":687,"dataGaName":688,"dataGaLocation":368},"/press/","press",{"text":690,"config":691,"menu":692},"Contact us",{"dataNavLevelOne":636},{"type":419,"columns":693},[694],{"items":695},[696,701,706],{"text":697,"config":698},"Talk to sales",{"href":699,"dataGaName":700,"dataGaLocation":368},"/sales/","talk to sales",{"text":702,"config":703},"Support portal",{"href":704,"dataGaName":705,"dataGaLocation":368},"https://support.gitlab.com/hc/en-us","support portal",{"text":707,"config":708},"Customer portal",{"href":709,"dataGaName":710,"dataGaLocation":368},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":712,"login":713,"suggestions":720},"Close",{"text":714,"link":715},"To search repositories and projects, login to",{"text":716,"config":717},"gitlab.com",{"href":382,"dataGaName":718,"dataGaLocation":719},"search login","search",{"text":721,"default":722},"Suggestions",[723,725,729,731,735,739],{"text":399,"config":724},{"href":404,"dataGaName":399,"dataGaLocation":719},{"text":726,"config":727},"Code Suggestions (AI)",{"href":728,"dataGaName":726,"dataGaLocation":719},"/solutions/code-suggestions/",{"text":435,"config":730},{"href":437,"dataGaName":435,"dataGaLocation":719},{"text":732,"config":733},"GitLab on AWS",{"href":734,"dataGaName":732,"dataGaLocation":719},"/partners/technology-partners/aws/",{"text":736,"config":737},"GitLab on Google Cloud",{"href":738,"dataGaName":736,"dataGaLocation":719},"/partners/technology-partners/google-cloud-platform/",{"text":740,"config":741},"Why GitLab?",{"href":412,"dataGaName":740,"dataGaLocation":719},{"freeTrial":743,"mobileIcon":748,"desktopIcon":753,"secondaryButton":756},{"text":744,"config":745},"Start free trial",{"href":746,"dataGaName":373,"dataGaLocation":747},"https://gitlab.com/-/trials/new/","nav",{"altText":749,"config":750},"Gitlab Icon",{"src":751,"dataGaName":752,"dataGaLocation":747},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":749,"config":754},{"src":755,"dataGaName":752,"dataGaLocation":747},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":757,"config":758},"Get Started",{"href":759,"dataGaName":760,"dataGaLocation":747},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":762,"mobileIcon":766,"desktopIcon":768},{"text":763,"config":764},"Learn more about GitLab Duo",{"href":404,"dataGaName":765,"dataGaLocation":747},"gitlab duo",{"altText":749,"config":767},{"src":751,"dataGaName":752,"dataGaLocation":747},{"altText":749,"config":769},{"src":755,"dataGaName":752,"dataGaLocation":747},{"button":771,"mobileIcon":776,"desktopIcon":778},{"text":772,"config":773},"/switch",{"href":774,"dataGaName":775,"dataGaLocation":747},"#contact","switch",{"altText":749,"config":777},{"src":751,"dataGaName":752,"dataGaLocation":747},{"altText":749,"config":779},{"src":780,"dataGaName":752,"dataGaLocation":747},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":782,"mobileIcon":787,"desktopIcon":789},{"text":783,"config":784},"Back to pricing",{"href":517,"dataGaName":785,"dataGaLocation":747,"icon":786},"back to pricing","GoBack",{"altText":749,"config":788},{"src":751,"dataGaName":752,"dataGaLocation":747},{"altText":749,"config":790},{"src":755,"dataGaName":752,"dataGaLocation":747},{"title":792,"titleMobile":793,"button":794,"config":799},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":410,"config":795},{"href":796,"dataGaName":797,"dataGaLocation":798},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":800,"disabled":346},"release",{"data":802},{"text":803,"source":804,"edit":810,"contribute":815,"config":820,"items":825,"minimal":1035},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":805,"config":806},"View page source",{"href":807,"dataGaName":808,"dataGaLocation":809},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":811,"config":812},"Edit this page",{"href":813,"dataGaName":814,"dataGaLocation":809},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":816,"config":817},"Please contribute",{"href":818,"dataGaName":819,"dataGaLocation":809},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":821,"facebook":822,"youtube":823,"linkedin":824},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[826,873,927,971,1003],{"title":515,"links":827,"subMenu":842},[828,832,837],{"text":829,"config":830},"View plans",{"href":517,"dataGaName":831,"dataGaLocation":809},"view plans",{"text":833,"config":834},"Why Premium?",{"href":835,"dataGaName":836,"dataGaLocation":809},"/pricing/premium/","why premium",{"text":838,"config":839},"Why Ultimate?",{"href":840,"dataGaName":841,"dataGaLocation":809},"/pricing/ultimate/","why ultimate",[843],{"title":844,"links":845},"Contact Us",[846,849,851,853,858,863,868],{"text":847,"config":848},"Contact sales",{"href":699,"dataGaName":378,"dataGaLocation":809},{"text":702,"config":850},{"href":704,"dataGaName":705,"dataGaLocation":809},{"text":707,"config":852},{"href":709,"dataGaName":710,"dataGaLocation":809},{"text":854,"config":855},"Status",{"href":856,"dataGaName":857,"dataGaLocation":809},"https://status.gitlab.com/","status",{"text":859,"config":860},"Terms of use",{"href":861,"dataGaName":862,"dataGaLocation":809},"/terms/","terms of use",{"text":864,"config":865},"Privacy statement",{"href":866,"dataGaName":867,"dataGaLocation":809},"/privacy/","privacy statement",{"text":869,"config":870},"Cookie preferences",{"dataGaName":871,"dataGaLocation":809,"id":872,"isOneTrustButton":349},"cookie preferences","ot-sdk-btn",{"title":415,"links":874,"subMenu":883},[875,879],{"text":876,"config":877},"DevSecOps platform",{"href":397,"dataGaName":878,"dataGaLocation":809},"devsecops platform",{"text":880,"config":881},"AI-Assisted Development",{"href":404,"dataGaName":882,"dataGaLocation":809},"ai-assisted development",[884],{"title":885,"links":886},"Topics",[887,892,897,902,907,912,917,922],{"text":888,"config":889},"CICD",{"href":890,"dataGaName":891,"dataGaLocation":809},"/topics/ci-cd/","cicd",{"text":893,"config":894},"GitOps",{"href":895,"dataGaName":896,"dataGaLocation":809},"/topics/gitops/","gitops",{"text":898,"config":899},"DevOps",{"href":900,"dataGaName":901,"dataGaLocation":809},"/topics/devops/","devops",{"text":903,"config":904},"Version Control",{"href":905,"dataGaName":906,"dataGaLocation":809},"/topics/version-control/","version control",{"text":908,"config":909},"DevSecOps",{"href":910,"dataGaName":911,"dataGaLocation":809},"/topics/devsecops/","devsecops",{"text":913,"config":914},"Cloud Native",{"href":915,"dataGaName":916,"dataGaLocation":809},"/topics/cloud-native/","cloud native",{"text":918,"config":919},"AI for Coding",{"href":920,"dataGaName":921,"dataGaLocation":809},"/topics/devops/ai-for-coding/","ai for coding",{"text":923,"config":924},"Agentic AI",{"href":925,"dataGaName":926,"dataGaLocation":809},"/topics/agentic-ai/","agentic ai",{"title":928,"links":929},"Solutions",[930,932,934,939,943,946,950,953,955,958,961,966],{"text":459,"config":931},{"href":454,"dataGaName":459,"dataGaLocation":809},{"text":448,"config":933},{"href":431,"dataGaName":432,"dataGaLocation":809},{"text":935,"config":936},"Agile development",{"href":937,"dataGaName":938,"dataGaLocation":809},"/solutions/agile-delivery/","agile delivery",{"text":940,"config":941},"SCM",{"href":444,"dataGaName":942,"dataGaLocation":809},"source code management",{"text":888,"config":944},{"href":437,"dataGaName":945,"dataGaLocation":809},"continuous integration & delivery",{"text":947,"config":948},"Value stream management",{"href":487,"dataGaName":949,"dataGaLocation":809},"value stream management",{"text":893,"config":951},{"href":952,"dataGaName":896,"dataGaLocation":809},"/solutions/gitops/",{"text":497,"config":954},{"href":500,"dataGaName":501,"dataGaLocation":809},{"text":956,"config":957},"Small business",{"href":506,"dataGaName":507,"dataGaLocation":809},{"text":959,"config":960},"Public sector",{"href":512,"dataGaName":513,"dataGaLocation":809},{"text":962,"config":963},"Education",{"href":964,"dataGaName":965,"dataGaLocation":809},"/solutions/education/","education",{"text":967,"config":968},"Financial services",{"href":969,"dataGaName":970,"dataGaLocation":809},"/solutions/finance/","financial services",{"title":520,"links":972},[973,975,977,979,982,984,987,989,991,993,995,997,999,1001],{"text":533,"config":974},{"href":535,"dataGaName":536,"dataGaLocation":809},{"text":538,"config":976},{"href":540,"dataGaName":541,"dataGaLocation":809},{"text":543,"config":978},{"href":545,"dataGaName":546,"dataGaLocation":809},{"text":548,"config":980},{"href":550,"dataGaName":981,"dataGaLocation":809},"docs",{"text":571,"config":983},{"href":573,"dataGaName":574,"dataGaLocation":809},{"text":985,"config":986},"What's new",{"href":631,"dataGaName":632,"dataGaLocation":809},{"text":566,"config":988},{"href":568,"dataGaName":569,"dataGaLocation":809},{"text":585,"config":990},{"href":587,"dataGaName":588,"dataGaLocation":809},{"text":593,"config":992},{"href":595,"dataGaName":596,"dataGaLocation":809},{"text":598,"config":994},{"href":600,"dataGaName":601,"dataGaLocation":809},{"text":603,"config":996},{"href":605,"dataGaName":606,"dataGaLocation":809},{"text":608,"config":998},{"href":610,"dataGaName":611,"dataGaLocation":809},{"text":613,"config":1000},{"href":615,"dataGaName":616,"dataGaLocation":809},{"text":618,"config":1002},{"href":620,"dataGaName":621,"dataGaLocation":809},{"title":634,"links":1004},[1005,1007,1009,1011,1013,1015,1019,1024,1026,1028,1030],{"text":642,"config":1006},{"href":644,"dataGaName":636,"dataGaLocation":809},{"text":647,"config":1008},{"href":649,"dataGaName":650,"dataGaLocation":809},{"text":655,"config":1010},{"href":657,"dataGaName":658,"dataGaLocation":809},{"text":660,"config":1012},{"href":662,"dataGaName":663,"dataGaLocation":809},{"text":665,"config":1014},{"href":667,"dataGaName":668,"dataGaLocation":809},{"text":1016,"config":1017},"Sustainability",{"href":1018,"dataGaName":1016,"dataGaLocation":809},"/sustainability/",{"text":1020,"config":1021},"Diversity, inclusion and belonging (DIB)",{"href":1022,"dataGaName":1023,"dataGaLocation":809},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":670,"config":1025},{"href":672,"dataGaName":673,"dataGaLocation":809},{"text":680,"config":1027},{"href":682,"dataGaName":683,"dataGaLocation":809},{"text":685,"config":1029},{"href":687,"dataGaName":688,"dataGaLocation":809},{"text":1031,"config":1032},"Modern Slavery Transparency Statement",{"href":1033,"dataGaName":1034,"dataGaLocation":809},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1036},[1037,1040,1043],{"text":1038,"config":1039},"Terms",{"href":861,"dataGaName":862,"dataGaLocation":809},{"text":1041,"config":1042},"Cookies",{"dataGaName":871,"dataGaLocation":809,"id":872,"isOneTrustButton":349},{"text":1044,"config":1045},"Privacy",{"href":866,"dataGaName":867,"dataGaLocation":809},[1047,1061],{"id":1048,"title":7,"body":345,"config":1049,"content":1051,"description":345,"extension":1055,"meta":1056,"navigation":349,"path":1057,"seo":1058,"stem":1059,"__hash__":1060},"blogAuthors/en-us/blog/authors/fabian-zimmer.yml",{"template":1050},"BlogAuthor",{"name":7,"config":1052},{"headshot":1053,"ctfId":1054},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750713473/q6awwqbxtg0a4x9gtmhs.png","3TK88UogcX5lx83kWMVuvI","yml",{},"/en-us/blog/authors/fabian-zimmer",{},"en-us/blog/authors/fabian-zimmer","qPVb4mKZuBff6-yly4-T5Bar6IdyXcx_tJHGlSL8QIA",{"id":1062,"title":8,"body":345,"config":1063,"content":1064,"description":345,"extension":1055,"meta":1068,"navigation":349,"path":1069,"seo":1070,"stem":1071,"__hash__":1072},"blogAuthors/en-us/blog/authors/douglas-alexandre.yml",{"template":1050},{"name":8,"config":1065},{"headshot":1066,"ctfId":1067},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","Douglas-Alexandre",{},"/en-us/blog/authors/douglas-alexandre",{},"en-us/blog/authors/douglas-alexandre","9oIVDz8T3S38e4STEdDnYFoN7NNjji5DBqDlbWomMxo",[1074,1083,1091],{"title":1075,"description":1076,"heroImage":1077,"category":341,"date":1078,"authors":1079,"slug":1082,"externalUrl":345},"Confidential AI for GitLab Self-Hosted","Give developers AI coding agents in GitLab Duo without source code leaving a hardware-encrypted boundary — no GPUs needed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png","2026-08-06",[1080,1081],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1084,"description":1085,"heroImage":1086,"category":341,"date":1087,"authors":1088,"slug":1090,"externalUrl":345},"Green DevOps: Why carbon measurement belongs in your CI/CD pipeline","CI/CD pipelines have a hidden carbon cost. Here's why measuring it matters, and how you can get started with Eco CI and Carmen in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-09",[1089],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1092,"description":1093,"heroImage":1094,"category":341,"date":1095,"authors":1096,"slug":1098,"externalUrl":345},"How to build CI/CD observability at scale","This practical guide to GitLab pipeline analytics helps self-managed users gain operational insights using Prometheus and Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-04-28",[1097],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1100},[1101,1115,1127,1139],{"id":1102,"categories":1103,"header":1105,"text":1106,"button":1107,"image":1112},"ai-modernization",[1104],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1108,"config":1109},"Get your AI maturity score",{"href":1110,"dataGaName":1111,"dataGaLocation":574},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1113},{"src":1114},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1116,"categories":1117,"header":1119,"text":1106,"button":1120,"image":1124},"devops-modernization",[1118,911],"product","Are you just managing tools or shipping innovation?",{"text":1121,"config":1122},"Get your DevOps maturity score",{"href":1123,"dataGaName":1111,"dataGaLocation":574},"/assessments/devops-modernization-assessment/",{"config":1125},{"src":1126},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1128,"categories":1129,"header":1131,"text":1106,"button":1132,"image":1136},"security-modernization",[1130],"security","Are you trading speed for security?",{"text":1133,"config":1134},"Get your security maturity score",{"href":1135,"dataGaName":1111,"dataGaLocation":574},"/assessments/security-modernization-assessment/",{"config":1137},{"src":1138},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1140,"paths":1141,"header":1144,"text":1145,"button":1146,"image":1151},"github-azure-migration",[1142,1143],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":1147,"config":1148},"See how GitLab compares to GitHub",{"href":1149,"dataGaName":1150,"dataGaLocation":574},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1152},{"src":1126},{"header":1154,"blurb":1155,"button":1156,"secondaryButton":1161},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1157,"config":1158},"Get your free trial",{"href":1159,"dataGaName":373,"dataGaLocation":1160},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":847,"config":1162},{"href":699,"dataGaName":378,"dataGaLocation":1160},1786803732592]