[{"data":1,"prerenderedAt":724},["ShallowReactive",2],{"/en-us/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features/":3,"navigation-en-us":45,"banner-en-us":460,"footer-en-us":475,"Chance Feick-Sam Wiskow":686,"next-steps-en-us":709},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":34,"_id":38,"_type":39,"title":40,"_source":41,"_file":42,"_stem":43,"_extension":44},"/en-us/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Building GitLab with GitLab: A multi-region service to deliver AI features","Discover how we built our first multi-region deployment for teams at GitLab using the platform's many features, helping create a frictionless developer experience for GitLab Duo users.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098664/Blog/Hero%20Images/Blog/Hero%20Images/building-gitlab-with-gitlab-no-type_building-gitlab-with-gitlab-no-type.png_1750098663794.png","https://about.gitlab.com/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Building GitLab with GitLab: A multi-region service to deliver AI features\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Chance Feick\"},{\"@type\":\"Person\",\"name\":\"Sam Wiskow\"}],\n        \"datePublished\": \"2024-09-12\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":20,"body":21,"category":22,"tags":23},[18,19],"Chance Feick","Sam Wiskow","2024-09-12","For GitLab Duo, real-time AI-powered capabilities like [Code Suggestions](https://about.gitlab.com/solutions/code-suggestions/) need low-latency response times for a frictionless developer experience. Users don’t want to interrupt their flow and wait for a code suggestion to show up. To ensure GitLab Duo can provide the right suggestion at the right time and meet high performance standards for critical AI infrastructure, GitLab recently launched our first multi-region service to deliver AI features.\n\nIn this article, we will cover the benefits of multi-region services, how we built an internal platform codenamed ‘Runway’ for provisioning and deploying multi-region services using GitLab features, and the lessons learned migrating to multi-region in production.\n\n## Background on the project\n\nRunway is GitLab’s internal platform as a service (PaaS) for provisioning, deploying, and operating containerized services. Runway's purpose is to enable GitLab service owners to self-serve infrastructure needs with production readiness out of the box, so application developers can focus on providing value to customers. As part of [our corporate value of dogfooding](https://handbook.gitlab.com/handbook/values/#results), the first iteration was built in 2023 by the Infrastructure department on top of core GitLab capabilities, such as continuous integration/continuous delivery ([CI/CD](https://about.gitlab.com/topics/ci-cd/)), environments, and deployments.\n\nBy establishing automated GitOps best practices, Runway services use infrastructure as code (IaC), merge requests (MRs), and CI/CD by default.\n\nGitLab Duo is primarily powered by [AI Gateway](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist), a satellite service written in Python outside of GitLab’s modular monolith written in Ruby. In cloud computing, a region is a geographical location of data centers operated by cloud providers.\n\n## Defining a multi-region strategy\n\nDeploying in a single region is a good starting point for most services, but can come with downsides when you are trying to reach a global audience. Users who are geographically far from where your service is deployed may experience different levels of service and responsiveness than those who are closer. This can lead to a poor user experience, even if your service is well built in all other respects.\n\nFor AI Gateway, it was important to meet global customers wherever they are located, whether on GitLab.com or self-managed instances using Cloud Connector. When a developer is deciding to accept or reject a code suggestion, milliseconds matter and can define the user experience.\n\n### Goals\n\nMulti-region deployments require more infrastructure complexity, but for use cases where latency is a core component of the user experience, the benefits often outweigh the downsides. First, multi-region deployments offer increased responsiveness to the user. By serving requests from locations closest to end users, latency can be significantly reduced. Second, multi-region deployments provide greater availability. With fault tolerance, services can fail over during a regional outage. There is a much lower chance of a service failing completely, meaning users should not be interrupted even in partial failures.\n\nBased on our goals for performance and availability, we used this opportunity to create a scalable multi-region strategy in Runway, which is built leveraging GitLab features.\n\n### Architecture\n\nIn SaaS platforms, GitLab.com’s infrastructure is hosted on Google Cloud Platform (GCP). As a result, Runway’s first supported platform runtime is Cloud Run. The initial workloads deployed on Runway are stateless satellite services (e.g., AI Gateway), so Cloud Run services are a good fit that provide a clear migration path to more complex and flexible platform runtimes, e.g. Kubernetes.\n\nBuilding Runway on top of GCP Cloud Run using GitLab has allowed us to iterate and tease out the right level of abstractions for service owners as part of a platform play in the Infrastructure department.\n\nTo serve traffic from multiple regions in Cloud Run, the multi-region deployment strategy must support global load balancing, and the provisioning and configuration of regional resources. Here’s a simplified diagram of the proposed architecture in GCP:\n\n![simplified diagram of the proposed architecture in GCP](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098671/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098671612.png)\n\nBy replicating Cloud Run services across multiple regions and configuring the existing global load balancing with serverless network endpoint group (NEG) backends, we’re able to serve traffic from multiple regions. For the remainder of the article, we’ll focus less on specifics of Cloud Run and more on how we’re building with GitLab.\n\n## Building a multi-region platform with GitLab\n\nNow that you have context about Runway, let's walk through how to build a multi-region platform using GitLab features.\n\n### Provision\n\nWhen building an internal platform, the first challenge is provisioning infrastructure for a service. In Runway, Provisioner is the component that is responsible for maintaining a service inventory and managing IaC for GCP resources using Terraform.\n\nTo provision a service, an application developer will open an MR to add a service project to the inventory using git, and Provisioner will create required resources, such as service accounts and identity and access management policies. When building this functionality with GitLab, Runway leverages [OpenID Connect (OIDC) with GPC Workload Identity Federation](https://docs.gitlab.com/ee/ci/cloud\\_services/google\\_cloud/) for managing IaC.\n\nAdditionally, Provisioner will create a deployment project for each service project. The purpose of creating separate projects for deployments is to ensure the [principle of least privilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/) by authenticating as a GCP service account with restricted permissions. Runway leverages the [Projects API](https://docs.gitlab.com/ee/api/projects.html) for creating projects with [Terraform provider](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs).\n\nFinally, Provisioner defines variables in the deployment project for the service account, so that deployment CI jobs can authenticate to GCP. Runway leverages [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) and [Job Token allowlist](https://docs.gitlab.com/ee/ci/jobs/ci\\_job\\_token.html\\#add-a-group-or-project-to-the-job-token-allowlist) to handle authentication and authorization.\n\nHere’s a simplified example of provisioning a multi-region service in the service inventory:\n\n```\n{\n  \"inventory\": [\n    {\n      \"name\": \"example-service\",\n      \"project_id\": 46267196,\n      \"regions\": [\n        \"europe-west1\",\n        \"us-east1\",\n        \"us-west1\"\n      ]\n    }\n  ]\n}\n```\n\nOnce provisioned, a deployment project and necessary infrastructure will be created for a service.\n\n### Configure\n\nAfter a service is provisioned, the next challenge is the configuration for a service. In Runway, [Reconciler](https://gitlab.com/gitlab-com/gl-infra/platform/runway/runwayctl) is a component that is responsible for configuring and deploying services by aligning the actual state with the desired state using Golang and Terraform.\n\nHere’s a simplified example of an application developer configuring GitLab CI/CD in their service project:\n\n```\n# .gitlab-ci.yml\nstages:\n  - validate\n  - runway_staging\n  - runway_production\n\ninclude:\n  - project: 'gitlab-com/gl-infra/platform/runway/runwayctl'\n    file: 'ci-tasks/service-project/runway.yml'\n    inputs:\n      runway_service_id: example-service\n      image: \"$CI_REGISTRY_IMAGE/${CI_PROJECT_NAME}:${CI_COMMIT_SHORT_SHA}\"\n      runway_version: v3.22.0\n\n# omitted for brevity\n```\n\nRunway provides sane default values for configuration that are based on our experience in delivering stable and reliable features to customers. Additionally, service owners can configure infrastructure using a service manifest file hosted in a service project. The service manifest uses JSON Schema for validation. When building this functionality with GitLab, Runway leverages [Pages](https://docs.gitlab.com/ee/user/project/pages/) for schema documentation.\n\nTo deliver this part of the platform, Runway leverages [CI/CD templates](https://docs.gitlab.com/ee/development/cicd/templates.html), [Releases](https://docs.gitlab.com/ee/user/project/releases/), and [Container Registry](https://docs.gitlab.com/ee/user/packages/container\\_registry/) for integrating with service projects.\n\nHere’s a simplified example of a service manifest:\n\n```\n# .runway/runway-production.yml\napiVersion: runway/v1\nkind: RunwayService\nspec:\n container_port: 8181\n regions:\n   - us-east1\n   - us-west1\n   - europe-west1\n\n# omitted for brevity\n```\n\nFor multi-region services, Runway injects an environment variable into the container instance runtime, e.g. RUNWAY\\_REGION, so application developers have the context to make any downstream dependencies regionally-aware, e.g. Vertex AI API.\n\nOnce configured, a service project will be integrated with a deployment project.\n\n### Deploy\n\nAfter a service project is configured, the next challenge is deploying a service. In Runway, Reconciler handles this by triggering a deployment job in the deployment project when an MR is merged to the main branch. When building this functionality with GitLab, Runway leverages [Trigger Pipelines](https://docs.gitlab.com/ee/ci/triggers/) and [Multi-Project Pipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream\\_pipelines.html\\#multi-project-pipelines) to trigger jobs from service project to deployment project.\n\n![trigger jobs from service project to deployment project](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098671612.png)\n\nOnce a pipeline is running in a deployment project, it will be deployed to an environment. By default, Runway will provision staging and production environments for all services. At this point, Reconciler will apply any Terraform resource changes for infrastructure. When building this functionality with GitLab, Runway leverages [Environments/Deployments](https://docs.gitlab.com/ee/ci/environments/) and [GitLab-managed Terraform state](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform\\_state.html) for each service.\n\n![Reconciler applies any Terraform resource changes for infrastructure](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098671614.png)\n\nRunway provides default application metrics for services. Additionally, custom metrics can be used by enabling a sidecar container with OpenTelemetry Collector configured to scrape Prometheus and remote write to Mimir. By providing observability out of the box, Runway is able to bake monitoring into CI/CD pipelines.\n\nExample scenarios include gradual rollouts for blue/green deployments, preventing promotions to production when staging is broken, or automatically rolling back to previous revision when elevated error rates occur in production.\n\n![Runway bakes monitoring into CI/CD pipelines](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098671615.png)\n\nOnce deployed, environments will serve the latest revision of a service. At this point, you should have a good understanding of some of the challenges that will be encountered, and how to solve them with GitLab features.\n\n## Migrating to multi-region in production\n\nAfter extending Runway components to support multi-region in Cloud Run, the final challenge was migrating from AI Gateway’s single-region deployment in production with zero downtime. Today, teams using Runway to deploy their services can self-serve on regions making a multi-region deployment just as simple as a single-region deployment. \n\nWe were able to iterate on building multi-region functionality without impacting existing infrastructure by using semantic versioning for Runway. Next, we’ll share some learnings from the migration that may inform how to operate services for an internal multi-region platform.\n\n### Dry run deployments\n\nIn Runway, Reconciler will apply Terraform changes in CI/CD. The trade-off is that plans cannot be verified in advance, which could risk inadvertently destroying or misconfiguring production infrastructure. To solve this problem, Runway will perform a “dry run” deployment for MRs.\n\n![\"Dry run\" deployment](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098671616.png)\n\nFor migrating AI Gateway, dry run deployments increased confidence and helped mitigate risk of downtime during rollout. When building an internal platform with GitLab, we recommend supporting dry run deployments from the start.\n\n### Regional observability\n\nIn Runway, existing observability was aggregated by assuming a single-region deployment. To solve this problem, Runway observability was retrofitted to include a new region label for Prometheus metrics.\n\nOnce metrics were retrofitted, we were able to introduce service level indicators (SLIs) for both regional Cloud Run services and global load balancing. Here’s an example dashboard screenshot for a general Runway service:\n\n![dashboard screenshot for a general Runway service](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098671617.png)\n\n***Note:** Data is not actual production data and is only for illustration purposes.*\n\nAdditionally, we were able to update our service level objectives (SLOs) to support regions. As a result, service owners could be alerted when a specific region experiences an elevated error rate, or increase in response times.\n\n![screenshot of alerts](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098671617.png)\n\n***Note:** Data is not actual production data and is only for illustration purposes.*\n\nFor migrating AI Gateway, regional observability increased confidence and helped provide more visibility into new infrastructure. When building an internal platform with GitLab, we recommend supporting regional observability from the start.\n\n### Self-service regions\n\nThe Infrastructure department successfully performed the initial migration of multi-region support for AI Gateway in production with zero downtime. Given the risk associated with rolling out a large infrastructure migration, it was important to ensure the service continued working as expected.\n\nShortly afterwards, service owners began self-serving additional regions to meet the growth of customers. At the time of writing, [GitLab Duo](https://about.gitlab.com/gitlab-duo/) is available in six regions around the globe and counting. Service owners are able to configure the desired regions, and Runway will provide guardrails along the way in a scalable solution.\n\nAdditionally, three other internal services have already started using multi-region functionality on Runway. Application developers have entirely self-served functionality, which validates that we’ve provided a good platform experience for service owners. For a platform play, a scalable solution like Runway is considered a good outcome since the Infrastructure department is no longer a blocker.\n\n## What’s next for Runway\n\nBased on how quickly we could iterate to provide results for customers, the SaaS Platforms department has continued to invest in Runway. We’ve grown the Runway team with additional contributors, started evolving the platform runtime (e.g. Google Kubernetes Engine), and continue dogfooding with tighter integration in the product.\n\nIf you’re interested in learning more, feel free to check out [https://gitlab.com/gitlab-com/gl-infra/platform/runway](https://gitlab.com/gitlab-com/gl-infra/platform/runway).\n\n## More Building GitLab with GitLab\n- [Why there is no MLOps without DevSecOps](https://about.gitlab.com/blog/there-is-no-mlops-without-devsecops/)\n- [Stress-testing Product Analytics](https://about.gitlab.com/blog/building-gitlab-with-gitlab-stress-testing-product-analytics/)\n- [Web API Fuzz Testing](https://about.gitlab.com/blog/building-gitlab-with-gitlab-api-fuzzing-workflow/)\n- [How GitLab.com inspired Dedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/)\n- [Expanding our security certification portfolio](https://about.gitlab.com/blog/building-gitlab-with-gitlab-expanding-our-security-certification-portfolio/)\n","engineering",[24,25,26,27,28,29,30,31,32,33],"CI/CD","CD","CI","inside GitLab","tutorial","performance","google","git","DevSecOps","AI/ML",{"slug":35,"featured":36,"template":37},"building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features",true,"BlogPost","content:en-us:blog:building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features.yml","yaml","Building Gitlab With Gitlab A Multi Region Service To Deliver Ai Features","content","en-us/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features.yml","en-us/blog/building-gitlab-with-gitlab-a-multi-region-service-to-deliver-ai-features","yml",{"_path":46,"_dir":47,"_draft":6,"_partial":6,"_locale":7,"data":48,"_id":456,"_type":39,"title":457,"_source":41,"_file":458,"_stem":459,"_extension":44},"/shared/en-us/main-navigation","en-us",{"logo":49,"freeTrial":54,"sales":59,"login":64,"items":69,"search":397,"minimal":428,"duo":447},{"config":50},{"href":51,"dataGaName":52,"dataGaLocation":53},"/","gitlab logo","header",{"text":55,"config":56},"Get free trial",{"href":57,"dataGaName":58,"dataGaLocation":53},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":60,"config":61},"Talk to sales",{"href":62,"dataGaName":63,"dataGaLocation":53},"/sales/","sales",{"text":65,"config":66},"Sign in",{"href":67,"dataGaName":68,"dataGaLocation":53},"https://gitlab.com/users/sign_in/","sign in",[70,114,208,213,318,378],{"text":71,"config":72,"cards":74,"footer":97},"Platform",{"dataNavLevelOne":73},"platform",[75,81,89],{"title":71,"description":76,"link":77},"The most comprehensive AI-powered DevSecOps Platform",{"text":78,"config":79},"Explore our Platform",{"href":80,"dataGaName":73,"dataGaLocation":53},"/platform/",{"title":82,"description":83,"link":84},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":85,"config":86},"Meet GitLab Duo",{"href":87,"dataGaName":88,"dataGaLocation":53},"/gitlab-duo/","gitlab duo ai",{"title":90,"description":91,"link":92},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":93,"config":94},"Learn more",{"href":95,"dataGaName":96,"dataGaLocation":53},"/why-gitlab/","why gitlab",{"title":98,"items":99},"Get started with",[100,105,110],{"text":101,"config":102},"Platform Engineering",{"href":103,"dataGaName":104,"dataGaLocation":53},"/solutions/platform-engineering/","platform engineering",{"text":106,"config":107},"Developer Experience",{"href":108,"dataGaName":109,"dataGaLocation":53},"/developer-experience/","Developer experience",{"text":111,"config":112},"MLOps",{"href":113,"dataGaName":111,"dataGaLocation":53},"/topics/devops/the-role-of-ai-in-devops/",{"text":115,"left":36,"config":116,"link":118,"lists":122,"footer":190},"Product",{"dataNavLevelOne":117},"solutions",{"text":119,"config":120},"View all Solutions",{"href":121,"dataGaName":117,"dataGaLocation":53},"/solutions/",[123,147,169],{"title":124,"description":125,"link":126,"items":131},"Automation","CI/CD and automation to accelerate deployment",{"config":127},{"icon":128,"href":129,"dataGaName":130,"dataGaLocation":53},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[132,135,139,143],{"text":24,"config":133},{"href":134,"dataGaLocation":53,"dataGaName":24},"/solutions/continuous-integration/",{"text":136,"config":137},"AI-Assisted Development",{"href":87,"dataGaLocation":53,"dataGaName":138},"AI assisted development",{"text":140,"config":141},"Source Code Management",{"href":142,"dataGaLocation":53,"dataGaName":140},"/solutions/source-code-management/",{"text":144,"config":145},"Automated Software Delivery",{"href":129,"dataGaLocation":53,"dataGaName":146},"Automated software delivery",{"title":148,"description":149,"link":150,"items":155},"Security","Deliver code faster without compromising security",{"config":151},{"href":152,"dataGaName":153,"dataGaLocation":53,"icon":154},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[156,159,164],{"text":157,"config":158},"Security & Compliance",{"href":152,"dataGaLocation":53,"dataGaName":157},{"text":160,"config":161},"Software Supply Chain Security",{"href":162,"dataGaLocation":53,"dataGaName":163},"/solutions/supply-chain/","Software supply chain security",{"text":165,"config":166},"Compliance & Governance",{"href":167,"dataGaLocation":53,"dataGaName":168},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":170,"link":171,"items":176},"Measurement",{"config":172},{"icon":173,"href":174,"dataGaName":175,"dataGaLocation":53},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[177,181,185],{"text":178,"config":179},"Visibility & Measurement",{"href":174,"dataGaLocation":53,"dataGaName":180},"Visibility and Measurement",{"text":182,"config":183},"Value Stream Management",{"href":184,"dataGaLocation":53,"dataGaName":182},"/solutions/value-stream-management/",{"text":186,"config":187},"Analytics & Insights",{"href":188,"dataGaLocation":53,"dataGaName":189},"/solutions/analytics-and-insights/","Analytics and insights",{"title":191,"items":192},"GitLab for",[193,198,203],{"text":194,"config":195},"Enterprise",{"href":196,"dataGaLocation":53,"dataGaName":197},"/enterprise/","enterprise",{"text":199,"config":200},"Small Business",{"href":201,"dataGaLocation":53,"dataGaName":202},"/small-business/","small business",{"text":204,"config":205},"Public Sector",{"href":206,"dataGaLocation":53,"dataGaName":207},"/solutions/public-sector/","public sector",{"text":209,"config":210},"Pricing",{"href":211,"dataGaName":212,"dataGaLocation":53,"dataNavLevelOne":212},"/pricing/","pricing",{"text":214,"config":215,"link":217,"lists":221,"feature":305},"Resources",{"dataNavLevelOne":216},"resources",{"text":218,"config":219},"View all resources",{"href":220,"dataGaName":216,"dataGaLocation":53},"/resources/",[222,255,277],{"title":223,"items":224},"Getting started",[225,230,235,240,245,250],{"text":226,"config":227},"Install",{"href":228,"dataGaName":229,"dataGaLocation":53},"/install/","install",{"text":231,"config":232},"Quick start guides",{"href":233,"dataGaName":234,"dataGaLocation":53},"/get-started/","quick setup checklists",{"text":236,"config":237},"Learn",{"href":238,"dataGaLocation":53,"dataGaName":239},"https://university.gitlab.com/","learn",{"text":241,"config":242},"Product documentation",{"href":243,"dataGaName":244,"dataGaLocation":53},"https://docs.gitlab.com/","product documentation",{"text":246,"config":247},"Best practice videos",{"href":248,"dataGaName":249,"dataGaLocation":53},"/getting-started-videos/","best practice videos",{"text":251,"config":252},"Integrations",{"href":253,"dataGaName":254,"dataGaLocation":53},"/integrations/","integrations",{"title":256,"items":257},"Discover",[258,263,267,272],{"text":259,"config":260},"Customer success stories",{"href":261,"dataGaName":262,"dataGaLocation":53},"/customers/","customer success stories",{"text":264,"config":265},"Blog",{"href":266,"dataGaName":5,"dataGaLocation":53},"/blog/",{"text":268,"config":269},"Remote",{"href":270,"dataGaName":271,"dataGaLocation":53},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":273,"config":274},"TeamOps",{"href":275,"dataGaName":276,"dataGaLocation":53},"/teamops/","teamops",{"title":278,"items":279},"Connect",[280,285,290,295,300],{"text":281,"config":282},"GitLab Services",{"href":283,"dataGaName":284,"dataGaLocation":53},"/services/","services",{"text":286,"config":287},"Community",{"href":288,"dataGaName":289,"dataGaLocation":53},"/community/","community",{"text":291,"config":292},"Forum",{"href":293,"dataGaName":294,"dataGaLocation":53},"https://forum.gitlab.com/","forum",{"text":296,"config":297},"Events",{"href":298,"dataGaName":299,"dataGaLocation":53},"/events/","events",{"text":301,"config":302},"Partners",{"href":303,"dataGaName":304,"dataGaLocation":53},"/partners/","partners",{"backgroundColor":306,"textColor":307,"text":308,"image":309,"link":313},"#2f2a6b","#fff","Insights for the future of software development",{"altText":310,"config":311},"the source promo card",{"src":312},"/images/navigation/the-source-promo-card.svg",{"text":314,"config":315},"Read the latest",{"href":316,"dataGaName":317,"dataGaLocation":53},"/the-source/","the source",{"text":319,"config":320,"lists":322},"Company",{"dataNavLevelOne":321},"company",[323],{"items":324},[325,330,336,338,343,348,353,358,363,368,373],{"text":326,"config":327},"About",{"href":328,"dataGaName":329,"dataGaLocation":53},"/company/","about",{"text":331,"config":332,"footerGa":335},"Jobs",{"href":333,"dataGaName":334,"dataGaLocation":53},"/jobs/","jobs",{"dataGaName":334},{"text":296,"config":337},{"href":298,"dataGaName":299,"dataGaLocation":53},{"text":339,"config":340},"Leadership",{"href":341,"dataGaName":342,"dataGaLocation":53},"/company/team/e-group/","leadership",{"text":344,"config":345},"Team",{"href":346,"dataGaName":347,"dataGaLocation":53},"/company/team/","team",{"text":349,"config":350},"Handbook",{"href":351,"dataGaName":352,"dataGaLocation":53},"https://handbook.gitlab.com/","handbook",{"text":354,"config":355},"Investor relations",{"href":356,"dataGaName":357,"dataGaLocation":53},"https://ir.gitlab.com/","investor relations",{"text":359,"config":360},"Trust Center",{"href":361,"dataGaName":362,"dataGaLocation":53},"/security/","trust center",{"text":364,"config":365},"AI Transparency Center",{"href":366,"dataGaName":367,"dataGaLocation":53},"/ai-transparency-center/","ai transparency center",{"text":369,"config":370},"Newsletter",{"href":371,"dataGaName":372,"dataGaLocation":53},"/company/contact/","newsletter",{"text":374,"config":375},"Press",{"href":376,"dataGaName":377,"dataGaLocation":53},"/press/","press",{"text":379,"config":380,"lists":381},"Contact us",{"dataNavLevelOne":321},[382],{"items":383},[384,387,392],{"text":60,"config":385},{"href":62,"dataGaName":386,"dataGaLocation":53},"talk to sales",{"text":388,"config":389},"Get help",{"href":390,"dataGaName":391,"dataGaLocation":53},"/support/","get help",{"text":393,"config":394},"Customer portal",{"href":395,"dataGaName":396,"dataGaLocation":53},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":398,"login":399,"suggestions":406},"Close",{"text":400,"link":401},"To search repositories and projects, login to",{"text":402,"config":403},"gitlab.com",{"href":67,"dataGaName":404,"dataGaLocation":405},"search login","search",{"text":407,"default":408},"Suggestions",[409,411,415,417,421,425],{"text":82,"config":410},{"href":87,"dataGaName":82,"dataGaLocation":405},{"text":412,"config":413},"Code Suggestions (AI)",{"href":414,"dataGaName":412,"dataGaLocation":405},"/solutions/code-suggestions/",{"text":24,"config":416},{"href":134,"dataGaName":24,"dataGaLocation":405},{"text":418,"config":419},"GitLab on AWS",{"href":420,"dataGaName":418,"dataGaLocation":405},"/partners/technology-partners/aws/",{"text":422,"config":423},"GitLab on Google Cloud",{"href":424,"dataGaName":422,"dataGaLocation":405},"/partners/technology-partners/google-cloud-platform/",{"text":426,"config":427},"Why GitLab?",{"href":95,"dataGaName":426,"dataGaLocation":405},{"freeTrial":429,"mobileIcon":434,"desktopIcon":439,"secondaryButton":442},{"text":430,"config":431},"Start free trial",{"href":432,"dataGaName":58,"dataGaLocation":433},"https://gitlab.com/-/trials/new/","nav",{"altText":435,"config":436},"Gitlab Icon",{"src":437,"dataGaName":438,"dataGaLocation":433},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":435,"config":440},{"src":441,"dataGaName":438,"dataGaLocation":433},"/images/brand/gitlab-logo-type.svg",{"text":443,"config":444},"Get Started",{"href":445,"dataGaName":446,"dataGaLocation":433},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":448,"mobileIcon":452,"desktopIcon":454},{"text":449,"config":450},"Learn more about GitLab Duo",{"href":87,"dataGaName":451,"dataGaLocation":433},"gitlab duo",{"altText":435,"config":453},{"src":437,"dataGaName":438,"dataGaLocation":433},{"altText":435,"config":455},{"src":441,"dataGaName":438,"dataGaLocation":433},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":461,"_dir":47,"_draft":6,"_partial":6,"_locale":7,"title":462,"button":463,"image":467,"config":470,"_id":472,"_type":39,"_source":41,"_file":473,"_stem":474,"_extension":44},"/shared/en-us/banner","is now in public beta!",{"text":93,"config":464},{"href":465,"dataGaName":466,"dataGaLocation":53},"/gitlab-duo/agent-platform/","duo banner",{"config":468},{"src":469},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":471},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":476,"_dir":47,"_draft":6,"_partial":6,"_locale":7,"data":477,"_id":682,"_type":39,"title":683,"_source":41,"_file":684,"_stem":685,"_extension":44},"/shared/en-us/main-footer",{"text":478,"source":479,"edit":485,"contribute":490,"config":495,"items":500,"minimal":674},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":480,"config":481},"View page source",{"href":482,"dataGaName":483,"dataGaLocation":484},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":486,"config":487},"Edit this page",{"href":488,"dataGaName":489,"dataGaLocation":484},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":491,"config":492},"Please contribute",{"href":493,"dataGaName":494,"dataGaLocation":484},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":496,"facebook":497,"youtube":498,"linkedin":499},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[501,524,581,610,644],{"title":71,"links":502,"subMenu":507},[503],{"text":504,"config":505},"DevSecOps platform",{"href":80,"dataGaName":506,"dataGaLocation":484},"devsecops platform",[508],{"title":209,"links":509},[510,514,519],{"text":511,"config":512},"View plans",{"href":211,"dataGaName":513,"dataGaLocation":484},"view plans",{"text":515,"config":516},"Why Premium?",{"href":517,"dataGaName":518,"dataGaLocation":484},"/pricing/premium/","why premium",{"text":520,"config":521},"Why Ultimate?",{"href":522,"dataGaName":523,"dataGaLocation":484},"/pricing/ultimate/","why ultimate",{"title":525,"links":526},"Solutions",[527,532,535,537,542,547,551,554,558,563,565,568,571,576],{"text":528,"config":529},"Digital transformation",{"href":530,"dataGaName":531,"dataGaLocation":484},"/topics/digital-transformation/","digital transformation",{"text":157,"config":533},{"href":152,"dataGaName":534,"dataGaLocation":484},"security & compliance",{"text":146,"config":536},{"href":129,"dataGaName":130,"dataGaLocation":484},{"text":538,"config":539},"Agile development",{"href":540,"dataGaName":541,"dataGaLocation":484},"/solutions/agile-delivery/","agile delivery",{"text":543,"config":544},"Cloud transformation",{"href":545,"dataGaName":546,"dataGaLocation":484},"/topics/cloud-native/","cloud transformation",{"text":548,"config":549},"SCM",{"href":142,"dataGaName":550,"dataGaLocation":484},"source code management",{"text":24,"config":552},{"href":134,"dataGaName":553,"dataGaLocation":484},"continuous integration & delivery",{"text":555,"config":556},"Value stream management",{"href":184,"dataGaName":557,"dataGaLocation":484},"value stream management",{"text":559,"config":560},"GitOps",{"href":561,"dataGaName":562,"dataGaLocation":484},"/solutions/gitops/","gitops",{"text":194,"config":564},{"href":196,"dataGaName":197,"dataGaLocation":484},{"text":566,"config":567},"Small business",{"href":201,"dataGaName":202,"dataGaLocation":484},{"text":569,"config":570},"Public sector",{"href":206,"dataGaName":207,"dataGaLocation":484},{"text":572,"config":573},"Education",{"href":574,"dataGaName":575,"dataGaLocation":484},"/solutions/education/","education",{"text":577,"config":578},"Financial services",{"href":579,"dataGaName":580,"dataGaLocation":484},"/solutions/finance/","financial services",{"title":214,"links":582},[583,585,587,589,592,594,596,598,600,602,604,606,608],{"text":226,"config":584},{"href":228,"dataGaName":229,"dataGaLocation":484},{"text":231,"config":586},{"href":233,"dataGaName":234,"dataGaLocation":484},{"text":236,"config":588},{"href":238,"dataGaName":239,"dataGaLocation":484},{"text":241,"config":590},{"href":243,"dataGaName":591,"dataGaLocation":484},"docs",{"text":264,"config":593},{"href":266,"dataGaName":5,"dataGaLocation":484},{"text":259,"config":595},{"href":261,"dataGaName":262,"dataGaLocation":484},{"text":268,"config":597},{"href":270,"dataGaName":271,"dataGaLocation":484},{"text":281,"config":599},{"href":283,"dataGaName":284,"dataGaLocation":484},{"text":273,"config":601},{"href":275,"dataGaName":276,"dataGaLocation":484},{"text":286,"config":603},{"href":288,"dataGaName":289,"dataGaLocation":484},{"text":291,"config":605},{"href":293,"dataGaName":294,"dataGaLocation":484},{"text":296,"config":607},{"href":298,"dataGaName":299,"dataGaLocation":484},{"text":301,"config":609},{"href":303,"dataGaName":304,"dataGaLocation":484},{"title":319,"links":611},[612,614,616,618,620,622,624,628,633,635,637,639],{"text":326,"config":613},{"href":328,"dataGaName":321,"dataGaLocation":484},{"text":331,"config":615},{"href":333,"dataGaName":334,"dataGaLocation":484},{"text":339,"config":617},{"href":341,"dataGaName":342,"dataGaLocation":484},{"text":344,"config":619},{"href":346,"dataGaName":347,"dataGaLocation":484},{"text":349,"config":621},{"href":351,"dataGaName":352,"dataGaLocation":484},{"text":354,"config":623},{"href":356,"dataGaName":357,"dataGaLocation":484},{"text":625,"config":626},"Sustainability",{"href":627,"dataGaName":625,"dataGaLocation":484},"/sustainability/",{"text":629,"config":630},"Diversity, inclusion and belonging (DIB)",{"href":631,"dataGaName":632,"dataGaLocation":484},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":359,"config":634},{"href":361,"dataGaName":362,"dataGaLocation":484},{"text":369,"config":636},{"href":371,"dataGaName":372,"dataGaLocation":484},{"text":374,"config":638},{"href":376,"dataGaName":377,"dataGaLocation":484},{"text":640,"config":641},"Modern Slavery Transparency Statement",{"href":642,"dataGaName":643,"dataGaLocation":484},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":645,"links":646},"Contact Us",[647,650,652,654,659,664,669],{"text":648,"config":649},"Contact an expert",{"href":62,"dataGaName":63,"dataGaLocation":484},{"text":388,"config":651},{"href":390,"dataGaName":391,"dataGaLocation":484},{"text":393,"config":653},{"href":395,"dataGaName":396,"dataGaLocation":484},{"text":655,"config":656},"Status",{"href":657,"dataGaName":658,"dataGaLocation":484},"https://status.gitlab.com/","status",{"text":660,"config":661},"Terms of use",{"href":662,"dataGaName":663,"dataGaLocation":484},"/terms/","terms of use",{"text":665,"config":666},"Privacy statement",{"href":667,"dataGaName":668,"dataGaLocation":484},"/privacy/","privacy statement",{"text":670,"config":671},"Cookie preferences",{"dataGaName":672,"dataGaLocation":484,"id":673,"isOneTrustButton":36},"cookie preferences","ot-sdk-btn",{"items":675},[676,678,680],{"text":660,"config":677},{"href":662,"dataGaName":663,"dataGaLocation":484},{"text":665,"config":679},{"href":667,"dataGaName":668,"dataGaLocation":484},{"text":670,"config":681},{"dataGaName":672,"dataGaLocation":484,"id":673,"isOneTrustButton":36},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[687,699],{"_path":688,"_dir":689,"_draft":6,"_partial":6,"_locale":7,"content":690,"config":694,"_id":696,"_type":39,"title":18,"_source":41,"_file":697,"_stem":698,"_extension":44},"/en-us/blog/authors/chance-feick","authors",{"name":18,"config":691},{"headshot":692,"ctfId":693},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666442/Blog/Author%20Headshots/chance_feick_headshot.png","18dtRbXV47xqf5iDrOIduM",{"template":695},"BlogAuthor","content:en-us:blog:authors:chance-feick.yml","en-us/blog/authors/chance-feick.yml","en-us/blog/authors/chance-feick",{"_path":700,"_dir":689,"_draft":6,"_partial":6,"_locale":7,"content":701,"config":705,"_id":706,"_type":39,"title":19,"_source":41,"_file":707,"_stem":708,"_extension":44},"/en-us/blog/authors/sam-wiskow",{"name":19,"config":702},{"headshot":703,"ctfId":704},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659433/Blog/Author%20Headshots/swiskow-headshot.jpg","swiskow",{"template":695},"content:en-us:blog:authors:sam-wiskow.yml","en-us/blog/authors/sam-wiskow.yml","en-us/blog/authors/sam-wiskow",{"_path":710,"_dir":47,"_draft":6,"_partial":6,"_locale":7,"header":711,"eyebrow":712,"blurb":713,"button":714,"secondaryButton":718,"_id":720,"_type":39,"title":721,"_source":41,"_file":722,"_stem":723,"_extension":44},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":55,"config":715},{"href":716,"dataGaName":58,"dataGaLocation":717},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":60,"config":719},{"href":62,"dataGaName":63,"dataGaLocation":717},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1754424493897]