[{"data":1,"prerenderedAt":737},["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":472,"footer-en-us":489,"Chance Feick-Sam Wiskow":699,"next-steps-en-us":722},{"_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\nSuggestions](https://about.gitlab.com/solutions/code-suggestions/) need\nlow-latency response times for a frictionless developer experience. Users\ndon’t want to interrupt their flow and wait for a code suggestion to show\nup. To ensure GitLab Duo can provide the right suggestion at the right time\nand meet high performance standards for critical AI infrastructure, GitLab\nrecently launched our first multi-region service to deliver AI features.\n\n\nIn this article, we will cover the benefits of multi-region services, how we\nbuilt an internal platform codenamed ‘Runway’ for provisioning and deploying\nmulti-region services using GitLab features, and the lessons learned\nmigrating to multi-region in production.\n\n\n## Background on the project\n\n\nRunway is GitLab’s internal platform as a service (PaaS) for provisioning,\ndeploying, and operating containerized services. Runway's purpose is to\nenable GitLab service owners to self-serve infrastructure needs with\nproduction readiness out of the box, so application developers can focus on\nproviding value to customers. As part of [our corporate value of\ndogfooding](https://handbook.gitlab.com/handbook/values/#results), the first\niteration was built in 2023 by the Infrastructure department on top of core\nGitLab capabilities, such as continuous integration/continuous delivery\n([CI/CD](https://about.gitlab.com/topics/ci-cd/)), environments, and\ndeployments.\n\n\nBy establishing automated GitOps best practices, Runway services use\ninfrastructure as code (IaC), merge requests (MRs), and CI/CD by default.\n\n\nGitLab Duo is primarily powered by [AI\nGateway](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist),\na satellite service written in Python outside of GitLab’s modular monolith\nwritten in Ruby. In cloud computing, a region is a geographical location of\ndata centers operated by cloud providers.\n\n\n## Defining a multi-region strategy\n\n\nDeploying in a single region is a good starting point for most services, but\ncan come with downsides when you are trying to reach a global audience.\nUsers who are geographically far from where your service is deployed may\nexperience different levels of service and responsiveness than those who are\ncloser. This can lead to a poor user experience, even if your service is\nwell built in all other respects.\n\n\nFor AI Gateway, it was important to meet global customers wherever they are\nlocated, whether on GitLab.com or self-managed instances using Cloud\nConnector. When a developer is deciding to accept or reject a code\nsuggestion, milliseconds matter and can define the user experience.\n\n\n### Goals\n\n\nMulti-region deployments require more infrastructure complexity, but for use\ncases where latency is a core component of the user experience, the benefits\noften outweigh the downsides. First, multi-region deployments offer\nincreased responsiveness to the user. By serving requests from locations\nclosest to end users, latency can be significantly reduced. Second,\nmulti-region deployments provide greater availability. With fault tolerance,\nservices can fail over during a regional outage. There is a much lower\nchance of a service failing completely, meaning users should not be\ninterrupted even in partial failures.\n\n\nBased on our goals for performance and availability, we used this\nopportunity to create a scalable multi-region strategy in Runway, which is\nbuilt leveraging GitLab features.\n\n\n### Architecture\n\n\nIn SaaS platforms, GitLab.com’s infrastructure is hosted on Google Cloud\nPlatform (GCP). As a result, Runway’s first supported platform runtime is\nCloud Run. The initial workloads deployed on Runway are stateless satellite\nservices (e.g., AI Gateway), so Cloud Run services are a good fit that\nprovide a clear migration path to more complex and flexible platform\nruntimes, e.g. Kubernetes.\n\n\nBuilding Runway on top of GCP Cloud Run using GitLab has allowed us to\niterate and tease out the right level of abstractions for service owners as\npart of a platform play in the Infrastructure department.\n\n\nTo serve traffic from multiple regions in Cloud Run, the multi-region\ndeployment strategy must support global load balancing, and the provisioning\nand configuration of regional resources. Here’s a simplified diagram of the\nproposed architecture in GCP:\n\n\n![simplified diagram of the proposed architecture in\nGCP](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098671/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750098671612.png)\n\n\nBy replicating Cloud Run services across multiple regions and configuring\nthe existing global load balancing with serverless network endpoint group\n(NEG) backends, we’re able to serve traffic from multiple regions. For the\nremainder of the article, we’ll focus less on specifics of Cloud Run and\nmore on how we’re building with GitLab.\n\n\n## Building a multi-region platform with GitLab\n\n\nNow that you have context about Runway, let's walk through how to build a\nmulti-region platform using GitLab features.\n\n\n### Provision\n\n\nWhen building an internal platform, the first challenge is provisioning\ninfrastructure for a service. In Runway, Provisioner is the component that\nis responsible for maintaining a service inventory and managing IaC for GCP\nresources using Terraform.\n\n\nTo provision a service, an application developer will open an MR to add a\nservice project to the inventory using git, and Provisioner will create\nrequired resources, such as service accounts and identity and access\nmanagement policies. When building this functionality with GitLab, Runway\nleverages [OpenID Connect (OIDC) with GPC Workload Identity\nFederation](https://docs.gitlab.com/ee/ci/cloud\\_services/google\\_cloud/)\nfor managing IaC.\n\n\nAdditionally, Provisioner will create a deployment project for each service\nproject. The purpose of creating separate projects for deployments is to\nensure the [principle of least\nprivilege](https://about.gitlab.com/blog/the-ultimate-guide-to-least-privilege-access-with-gitlab/)\nby authenticating as a GCP service account with restricted permissions.\nRunway leverages the [Projects\nAPI](https://docs.gitlab.com/ee/api/projects.html) for creating projects\nwith [Terraform\nprovider](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs).\n\n\nFinally, Provisioner defines variables in the deployment project for the\nservice account, so that deployment CI jobs can authenticate to GCP. Runway\nleverages [CI/CD variables](https://docs.gitlab.com/ee/ci/variables/) and\n[Job Token\nallowlist](https://docs.gitlab.com/ee/ci/jobs/ci\\_job\\_token.html\\#add-a-group-or-project-to-the-job-token-allowlist)\nto handle authentication and authorization.\n\n\nHere’s a simplified example of provisioning a multi-region service in the\nservice inventory:\n\n\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```\n\n\nOnce provisioned, a deployment project and necessary infrastructure will be\ncreated for a service.\n\n\n### Configure\n\n\nAfter a service is provisioned, the next challenge is the configuration for\na service. In Runway,\n[Reconciler](https://gitlab.com/gitlab-com/gl-infra/platform/runway/runwayctl)\nis a component that is responsible for configuring and deploying services by\naligning the actual state with the desired state using Golang and Terraform.\n\n\nHere’s a simplified example of an application developer configuring GitLab\nCI/CD in their service project:\n\n\n```\n\n# .gitlab-ci.yml\n\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```\n\n\nRunway provides sane default values for configuration that are based on our\nexperience in delivering stable and reliable features to customers.\nAdditionally, service owners can configure infrastructure using a service\nmanifest file hosted in a service project. The service manifest uses JSON\nSchema for validation. When building this functionality with GitLab, Runway\nleverages [Pages](https://docs.gitlab.com/ee/user/project/pages/) for schema\ndocumentation.\n\n\nTo deliver this part of the platform, Runway leverages [CI/CD\ntemplates](https://docs.gitlab.com/ee/development/cicd/templates.html),\n[Releases](https://docs.gitlab.com/ee/user/project/releases/), and\n[Container\nRegistry](https://docs.gitlab.com/ee/user/packages/container\\_registry/) for\nintegrating with service projects.\n\n\nHere’s a simplified example of a service manifest:\n\n\n```\n\n# .runway/runway-production.yml\n\napiVersion: runway/v1\n\nkind: RunwayService\n\nspec:\n container_port: 8181\n regions:\n   - us-east1\n   - us-west1\n   - europe-west1\n\n# omitted for brevity\n\n```\n\n\nFor multi-region services, Runway injects an environment variable into the\ncontainer instance runtime, e.g. RUNWAY\\_REGION, so application developers\nhave the context to make any downstream dependencies regionally-aware, e.g.\nVertex AI API.\n\n\nOnce configured, a service project will be integrated with a deployment\nproject.\n\n\n### Deploy\n\n\nAfter a service project is configured, the next challenge is deploying a\nservice. In Runway, Reconciler handles this by triggering a deployment job\nin the deployment project when an MR is merged to the main branch. When\nbuilding this functionality with GitLab, Runway leverages [Trigger\nPipelines](https://docs.gitlab.com/ee/ci/triggers/) and [Multi-Project\nPipelines](https://docs.gitlab.com/ee/ci/pipelines/downstream\\_pipelines.html\\#multi-project-pipelines)\nto trigger jobs from service project to deployment project.\n\n\n![trigger jobs from service project to deployment\nproject](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image5_aHR0cHM6_1750098671612.png)\n\n\nOnce a pipeline is running in a deployment project, it will be deployed to\nan environment. By default, Runway will provision staging and production\nenvironments for all services. At this point, Reconciler will apply any\nTerraform resource changes for infrastructure. When building this\nfunctionality with GitLab, Runway leverages\n[Environments/Deployments](https://docs.gitlab.com/ee/ci/environments/) and\n[GitLab-managed Terraform\nstate](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform\\_state.html)\nfor each service.\n\n\n![Reconciler applies any Terraform resource changes for\ninfrastructure](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image1_aHR0cHM6_1750098671614.png)\n\n\nRunway provides default application metrics for services. Additionally,\ncustom metrics can be used by enabling a sidecar container with\nOpenTelemetry Collector configured to scrape Prometheus and remote write to\nMimir. By providing observability out of the box, Runway is able to bake\nmonitoring into CI/CD pipelines.\n\n\nExample scenarios include gradual rollouts for blue/green deployments,\npreventing promotions to production when staging is broken, or automatically\nrolling back to previous revision when elevated error rates occur in\nproduction.\n\n\n![Runway bakes monitoring into CI/CD\npipelines](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750098671615.png)\n\n\nOnce deployed, environments will serve the latest revision of a service. At\nthis point, you should have a good understanding of some of the challenges\nthat will be encountered, and how to solve them with GitLab features.\n\n\n## Migrating to multi-region in production\n\n\nAfter extending Runway components to support multi-region in Cloud Run, the\nfinal challenge was migrating from AI Gateway’s single-region deployment in\nproduction with zero downtime. Today, teams using Runway to deploy their\nservices can self-serve on regions making a multi-region deployment just as\nsimple as a single-region deployment. \n\n\nWe were able to iterate on building multi-region functionality without\nimpacting existing infrastructure by using semantic versioning for Runway.\nNext, we’ll share some learnings from the migration that may inform how to\noperate services for an internal multi-region platform.\n\n\n### Dry run deployments\n\n\nIn Runway, Reconciler will apply Terraform changes in CI/CD. The trade-off\nis that plans cannot be verified in advance, which could risk inadvertently\ndestroying or misconfiguring production infrastructure. To solve this\nproblem, Runway will perform a “dry run” deployment for MRs.\n\n\n![\"Dry run\"\ndeployment](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image6_aHR0cHM6_1750098671616.png)\n\n\nFor migrating AI Gateway, dry run deployments increased confidence and\nhelped mitigate risk of downtime during rollout. When building an internal\nplatform with GitLab, we recommend supporting dry run deployments from the\nstart.\n\n\n### Regional observability\n\n\nIn Runway, existing observability was aggregated by assuming a single-region\ndeployment. To solve this problem, Runway observability was retrofitted to\ninclude a new region label for Prometheus metrics.\n\n\nOnce metrics were retrofitted, we were able to introduce service level\nindicators (SLIs) for both regional Cloud Run services and global load\nbalancing. Here’s an example dashboard screenshot for a general Runway\nservice:\n\n\n![dashboard screenshot for a general Runway\nservice](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image3_aHR0cHM6_1750098671617.png)\n\n\n***Note:** Data is not actual production data and is only for illustration\npurposes.*\n\n\nAdditionally, we were able to update our service level objectives (SLOs) to\nsupport regions. As a result, service owners could be alerted when a\nspecific region experiences an elevated error rate, or increase in response\ntimes.\n\n\n![screenshot of\nalerts](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750098672/Blog/Content%20Images/Blog/Content%20Images/image4_aHR0cHM6_1750098671617.png)\n\n\n***Note:** Data is not actual production data and is only for illustration\npurposes.*\n\n\nFor migrating AI Gateway, regional observability increased confidence and\nhelped provide more visibility into new infrastructure. When building an\ninternal platform with GitLab, we recommend supporting regional\nobservability from the start.\n\n\n### Self-service regions\n\n\nThe Infrastructure department successfully performed the initial migration\nof multi-region support for AI Gateway in production with zero downtime.\nGiven the risk associated with rolling out a large infrastructure migration,\nit was important to ensure the service continued working as expected.\n\n\nShortly afterwards, service owners began self-serving additional regions to\nmeet the growth of customers. At the time of writing, [GitLab\nDuo](https://about.gitlab.com/gitlab-duo/) is available in six regions\naround the globe and counting. Service owners are able to configure the\ndesired regions, and Runway will provide guardrails along the way in a\nscalable solution.\n\n\nAdditionally, three other internal services have already started using\nmulti-region functionality on Runway. Application developers have entirely\nself-served functionality, which validates that we’ve provided a good\nplatform experience for service owners. For a platform play, a scalable\nsolution like Runway is considered a good outcome since the Infrastructure\ndepartment is no longer a blocker.\n\n\n## What’s next for Runway\n\n\nBased on how quickly we could iterate to provide results for customers, the\nSaaS Platforms department has continued to invest in Runway. We’ve grown the\nRunway team with additional contributors, started evolving the platform\nruntime (e.g. Google Kubernetes Engine), and continue dogfooding with\ntighter integration in the product.\n\n\nIf you’re interested in learning more, feel free to check out\n[https://gitlab.com/gitlab-com/gl-infra/platform/runway](https://gitlab.com/gitlab-com/gl-infra/platform/runway).\n\n\n## More Building GitLab with GitLab\n\n- [Why there is no MLOps without\nDevSecOps](https://about.gitlab.com/blog/there-is-no-mlops-without-devsecops/)\n\n- [Stress-testing Product\nAnalytics](https://about.gitlab.com/blog/building-gitlab-with-gitlab-stress-testing-product-analytics/)\n\n- [Web API Fuzz\nTesting](https://about.gitlab.com/blog/building-gitlab-with-gitlab-api-fuzzing-workflow/)\n\n- [How GitLab.com inspired\nDedicated](https://about.gitlab.com/blog/building-gitlab-with-gitlabcom-how-gitlab-inspired-dedicated/)\n\n- [Expanding our security certification\nportfolio](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":468,"_type":39,"title":469,"_source":41,"_file":470,"_stem":471,"_extension":44},"/shared/en-us/main-navigation","en-us",{"logo":49,"freeTrial":54,"sales":59,"login":64,"items":69,"search":399,"minimal":430,"duo":449,"pricingDeployment":458},{"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,210,215,320,380],{"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":192},"Product",{"dataNavLevelOne":117},"solutions",{"text":119,"config":120},"View all Solutions",{"href":121,"dataGaName":117,"dataGaLocation":53},"/solutions/",[123,147,171],{"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,161,166],{"text":157,"config":158},"Application Security Testing",{"href":159,"dataGaName":160,"dataGaLocation":53},"/solutions/application-security-testing/","Application security testing",{"text":162,"config":163},"Software Supply Chain Security",{"href":164,"dataGaLocation":53,"dataGaName":165},"/solutions/supply-chain/","Software supply chain security",{"text":167,"config":168},"Software Compliance",{"href":169,"dataGaName":170,"dataGaLocation":53},"/solutions/software-compliance/","software compliance",{"title":172,"link":173,"items":178},"Measurement",{"config":174},{"icon":175,"href":176,"dataGaName":177,"dataGaLocation":53},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[179,183,187],{"text":180,"config":181},"Visibility & Measurement",{"href":176,"dataGaLocation":53,"dataGaName":182},"Visibility and Measurement",{"text":184,"config":185},"Value Stream Management",{"href":186,"dataGaLocation":53,"dataGaName":184},"/solutions/value-stream-management/",{"text":188,"config":189},"Analytics & Insights",{"href":190,"dataGaLocation":53,"dataGaName":191},"/solutions/analytics-and-insights/","Analytics and insights",{"title":193,"items":194},"GitLab for",[195,200,205],{"text":196,"config":197},"Enterprise",{"href":198,"dataGaLocation":53,"dataGaName":199},"/enterprise/","enterprise",{"text":201,"config":202},"Small Business",{"href":203,"dataGaLocation":53,"dataGaName":204},"/small-business/","small business",{"text":206,"config":207},"Public Sector",{"href":208,"dataGaLocation":53,"dataGaName":209},"/solutions/public-sector/","public sector",{"text":211,"config":212},"Pricing",{"href":213,"dataGaName":214,"dataGaLocation":53,"dataNavLevelOne":214},"/pricing/","pricing",{"text":216,"config":217,"link":219,"lists":223,"feature":307},"Resources",{"dataNavLevelOne":218},"resources",{"text":220,"config":221},"View all resources",{"href":222,"dataGaName":218,"dataGaLocation":53},"/resources/",[224,257,279],{"title":225,"items":226},"Getting started",[227,232,237,242,247,252],{"text":228,"config":229},"Install",{"href":230,"dataGaName":231,"dataGaLocation":53},"/install/","install",{"text":233,"config":234},"Quick start guides",{"href":235,"dataGaName":236,"dataGaLocation":53},"/get-started/","quick setup checklists",{"text":238,"config":239},"Learn",{"href":240,"dataGaLocation":53,"dataGaName":241},"https://university.gitlab.com/","learn",{"text":243,"config":244},"Product documentation",{"href":245,"dataGaName":246,"dataGaLocation":53},"https://docs.gitlab.com/","product documentation",{"text":248,"config":249},"Best practice videos",{"href":250,"dataGaName":251,"dataGaLocation":53},"/getting-started-videos/","best practice videos",{"text":253,"config":254},"Integrations",{"href":255,"dataGaName":256,"dataGaLocation":53},"/integrations/","integrations",{"title":258,"items":259},"Discover",[260,265,269,274],{"text":261,"config":262},"Customer success stories",{"href":263,"dataGaName":264,"dataGaLocation":53},"/customers/","customer success stories",{"text":266,"config":267},"Blog",{"href":268,"dataGaName":5,"dataGaLocation":53},"/blog/",{"text":270,"config":271},"Remote",{"href":272,"dataGaName":273,"dataGaLocation":53},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":275,"config":276},"TeamOps",{"href":277,"dataGaName":278,"dataGaLocation":53},"/teamops/","teamops",{"title":280,"items":281},"Connect",[282,287,292,297,302],{"text":283,"config":284},"GitLab Services",{"href":285,"dataGaName":286,"dataGaLocation":53},"/services/","services",{"text":288,"config":289},"Community",{"href":290,"dataGaName":291,"dataGaLocation":53},"/community/","community",{"text":293,"config":294},"Forum",{"href":295,"dataGaName":296,"dataGaLocation":53},"https://forum.gitlab.com/","forum",{"text":298,"config":299},"Events",{"href":300,"dataGaName":301,"dataGaLocation":53},"/events/","events",{"text":303,"config":304},"Partners",{"href":305,"dataGaName":306,"dataGaLocation":53},"/partners/","partners",{"backgroundColor":308,"textColor":309,"text":310,"image":311,"link":315},"#2f2a6b","#fff","Insights for the future of software development",{"altText":312,"config":313},"the source promo card",{"src":314},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":316,"config":317},"Read the latest",{"href":318,"dataGaName":319,"dataGaLocation":53},"/the-source/","the source",{"text":321,"config":322,"lists":324},"Company",{"dataNavLevelOne":323},"company",[325],{"items":326},[327,332,338,340,345,350,355,360,365,370,375],{"text":328,"config":329},"About",{"href":330,"dataGaName":331,"dataGaLocation":53},"/company/","about",{"text":333,"config":334,"footerGa":337},"Jobs",{"href":335,"dataGaName":336,"dataGaLocation":53},"/jobs/","jobs",{"dataGaName":336},{"text":298,"config":339},{"href":300,"dataGaName":301,"dataGaLocation":53},{"text":341,"config":342},"Leadership",{"href":343,"dataGaName":344,"dataGaLocation":53},"/company/team/e-group/","leadership",{"text":346,"config":347},"Team",{"href":348,"dataGaName":349,"dataGaLocation":53},"/company/team/","team",{"text":351,"config":352},"Handbook",{"href":353,"dataGaName":354,"dataGaLocation":53},"https://handbook.gitlab.com/","handbook",{"text":356,"config":357},"Investor relations",{"href":358,"dataGaName":359,"dataGaLocation":53},"https://ir.gitlab.com/","investor relations",{"text":361,"config":362},"Trust Center",{"href":363,"dataGaName":364,"dataGaLocation":53},"/security/","trust center",{"text":366,"config":367},"AI Transparency Center",{"href":368,"dataGaName":369,"dataGaLocation":53},"/ai-transparency-center/","ai transparency center",{"text":371,"config":372},"Newsletter",{"href":373,"dataGaName":374,"dataGaLocation":53},"/company/contact/","newsletter",{"text":376,"config":377},"Press",{"href":378,"dataGaName":379,"dataGaLocation":53},"/press/","press",{"text":381,"config":382,"lists":383},"Contact us",{"dataNavLevelOne":323},[384],{"items":385},[386,389,394],{"text":60,"config":387},{"href":62,"dataGaName":388,"dataGaLocation":53},"talk to sales",{"text":390,"config":391},"Get help",{"href":392,"dataGaName":393,"dataGaLocation":53},"/support/","get help",{"text":395,"config":396},"Customer portal",{"href":397,"dataGaName":398,"dataGaLocation":53},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":400,"login":401,"suggestions":408},"Close",{"text":402,"link":403},"To search repositories and projects, login to",{"text":404,"config":405},"gitlab.com",{"href":67,"dataGaName":406,"dataGaLocation":407},"search login","search",{"text":409,"default":410},"Suggestions",[411,413,417,419,423,427],{"text":82,"config":412},{"href":87,"dataGaName":82,"dataGaLocation":407},{"text":414,"config":415},"Code Suggestions (AI)",{"href":416,"dataGaName":414,"dataGaLocation":407},"/solutions/code-suggestions/",{"text":24,"config":418},{"href":134,"dataGaName":24,"dataGaLocation":407},{"text":420,"config":421},"GitLab on AWS",{"href":422,"dataGaName":420,"dataGaLocation":407},"/partners/technology-partners/aws/",{"text":424,"config":425},"GitLab on Google Cloud",{"href":426,"dataGaName":424,"dataGaLocation":407},"/partners/technology-partners/google-cloud-platform/",{"text":428,"config":429},"Why GitLab?",{"href":95,"dataGaName":428,"dataGaLocation":407},{"freeTrial":431,"mobileIcon":436,"desktopIcon":441,"secondaryButton":444},{"text":432,"config":433},"Start free trial",{"href":434,"dataGaName":58,"dataGaLocation":435},"https://gitlab.com/-/trials/new/","nav",{"altText":437,"config":438},"Gitlab Icon",{"src":439,"dataGaName":440,"dataGaLocation":435},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":437,"config":442},{"src":443,"dataGaName":440,"dataGaLocation":435},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":445,"config":446},"Get Started",{"href":447,"dataGaName":448,"dataGaLocation":435},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":450,"mobileIcon":454,"desktopIcon":456},{"text":451,"config":452},"Learn more about GitLab Duo",{"href":87,"dataGaName":453,"dataGaLocation":435},"gitlab duo",{"altText":437,"config":455},{"src":439,"dataGaName":440,"dataGaLocation":435},{"altText":437,"config":457},{"src":443,"dataGaName":440,"dataGaLocation":435},{"freeTrial":459,"mobileIcon":464,"desktopIcon":466},{"text":460,"config":461},"Back to pricing",{"href":213,"dataGaName":462,"dataGaLocation":435,"icon":463},"back to pricing","GoBack",{"altText":437,"config":465},{"src":439,"dataGaName":440,"dataGaLocation":435},{"altText":437,"config":467},{"src":443,"dataGaName":440,"dataGaLocation":435},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":473,"_dir":47,"_draft":6,"_partial":6,"_locale":7,"title":474,"button":475,"image":480,"config":484,"_id":486,"_type":39,"_source":41,"_file":487,"_stem":488,"_extension":44},"/shared/en-us/banner","is now in public beta!",{"text":476,"config":477},"Try the Beta",{"href":478,"dataGaName":479,"dataGaLocation":53},"/gitlab-duo/agent-platform/","duo banner",{"altText":481,"config":482},"GitLab Duo Agent Platform",{"src":483},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":485},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":490,"_dir":47,"_draft":6,"_partial":6,"_locale":7,"data":491,"_id":695,"_type":39,"title":696,"_source":41,"_file":697,"_stem":698,"_extension":44},"/shared/en-us/main-footer",{"text":492,"source":493,"edit":499,"contribute":504,"config":509,"items":514,"minimal":687},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":494,"config":495},"View page source",{"href":496,"dataGaName":497,"dataGaLocation":498},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":500,"config":501},"Edit this page",{"href":502,"dataGaName":503,"dataGaLocation":498},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":505,"config":506},"Please contribute",{"href":507,"dataGaName":508,"dataGaLocation":498},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":510,"facebook":511,"youtube":512,"linkedin":513},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[515,538,594,623,657],{"title":71,"links":516,"subMenu":521},[517],{"text":518,"config":519},"DevSecOps platform",{"href":80,"dataGaName":520,"dataGaLocation":498},"devsecops platform",[522],{"title":211,"links":523},[524,528,533],{"text":525,"config":526},"View plans",{"href":213,"dataGaName":527,"dataGaLocation":498},"view plans",{"text":529,"config":530},"Why Premium?",{"href":531,"dataGaName":532,"dataGaLocation":498},"/pricing/premium/","why premium",{"text":534,"config":535},"Why Ultimate?",{"href":536,"dataGaName":537,"dataGaLocation":498},"/pricing/ultimate/","why ultimate",{"title":539,"links":540},"Solutions",[541,546,548,550,555,560,564,567,571,576,578,581,584,589],{"text":542,"config":543},"Digital transformation",{"href":544,"dataGaName":545,"dataGaLocation":498},"/topics/digital-transformation/","digital transformation",{"text":157,"config":547},{"href":159,"dataGaName":157,"dataGaLocation":498},{"text":146,"config":549},{"href":129,"dataGaName":130,"dataGaLocation":498},{"text":551,"config":552},"Agile development",{"href":553,"dataGaName":554,"dataGaLocation":498},"/solutions/agile-delivery/","agile delivery",{"text":556,"config":557},"Cloud transformation",{"href":558,"dataGaName":559,"dataGaLocation":498},"/topics/cloud-native/","cloud transformation",{"text":561,"config":562},"SCM",{"href":142,"dataGaName":563,"dataGaLocation":498},"source code management",{"text":24,"config":565},{"href":134,"dataGaName":566,"dataGaLocation":498},"continuous integration & delivery",{"text":568,"config":569},"Value stream management",{"href":186,"dataGaName":570,"dataGaLocation":498},"value stream management",{"text":572,"config":573},"GitOps",{"href":574,"dataGaName":575,"dataGaLocation":498},"/solutions/gitops/","gitops",{"text":196,"config":577},{"href":198,"dataGaName":199,"dataGaLocation":498},{"text":579,"config":580},"Small business",{"href":203,"dataGaName":204,"dataGaLocation":498},{"text":582,"config":583},"Public sector",{"href":208,"dataGaName":209,"dataGaLocation":498},{"text":585,"config":586},"Education",{"href":587,"dataGaName":588,"dataGaLocation":498},"/solutions/education/","education",{"text":590,"config":591},"Financial services",{"href":592,"dataGaName":593,"dataGaLocation":498},"/solutions/finance/","financial services",{"title":216,"links":595},[596,598,600,602,605,607,609,611,613,615,617,619,621],{"text":228,"config":597},{"href":230,"dataGaName":231,"dataGaLocation":498},{"text":233,"config":599},{"href":235,"dataGaName":236,"dataGaLocation":498},{"text":238,"config":601},{"href":240,"dataGaName":241,"dataGaLocation":498},{"text":243,"config":603},{"href":245,"dataGaName":604,"dataGaLocation":498},"docs",{"text":266,"config":606},{"href":268,"dataGaName":5,"dataGaLocation":498},{"text":261,"config":608},{"href":263,"dataGaName":264,"dataGaLocation":498},{"text":270,"config":610},{"href":272,"dataGaName":273,"dataGaLocation":498},{"text":283,"config":612},{"href":285,"dataGaName":286,"dataGaLocation":498},{"text":275,"config":614},{"href":277,"dataGaName":278,"dataGaLocation":498},{"text":288,"config":616},{"href":290,"dataGaName":291,"dataGaLocation":498},{"text":293,"config":618},{"href":295,"dataGaName":296,"dataGaLocation":498},{"text":298,"config":620},{"href":300,"dataGaName":301,"dataGaLocation":498},{"text":303,"config":622},{"href":305,"dataGaName":306,"dataGaLocation":498},{"title":321,"links":624},[625,627,629,631,633,635,637,641,646,648,650,652],{"text":328,"config":626},{"href":330,"dataGaName":323,"dataGaLocation":498},{"text":333,"config":628},{"href":335,"dataGaName":336,"dataGaLocation":498},{"text":341,"config":630},{"href":343,"dataGaName":344,"dataGaLocation":498},{"text":346,"config":632},{"href":348,"dataGaName":349,"dataGaLocation":498},{"text":351,"config":634},{"href":353,"dataGaName":354,"dataGaLocation":498},{"text":356,"config":636},{"href":358,"dataGaName":359,"dataGaLocation":498},{"text":638,"config":639},"Sustainability",{"href":640,"dataGaName":638,"dataGaLocation":498},"/sustainability/",{"text":642,"config":643},"Diversity, inclusion and belonging (DIB)",{"href":644,"dataGaName":645,"dataGaLocation":498},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":361,"config":647},{"href":363,"dataGaName":364,"dataGaLocation":498},{"text":371,"config":649},{"href":373,"dataGaName":374,"dataGaLocation":498},{"text":376,"config":651},{"href":378,"dataGaName":379,"dataGaLocation":498},{"text":653,"config":654},"Modern Slavery Transparency Statement",{"href":655,"dataGaName":656,"dataGaLocation":498},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":658,"links":659},"Contact Us",[660,663,665,667,672,677,682],{"text":661,"config":662},"Contact an expert",{"href":62,"dataGaName":63,"dataGaLocation":498},{"text":390,"config":664},{"href":392,"dataGaName":393,"dataGaLocation":498},{"text":395,"config":666},{"href":397,"dataGaName":398,"dataGaLocation":498},{"text":668,"config":669},"Status",{"href":670,"dataGaName":671,"dataGaLocation":498},"https://status.gitlab.com/","status",{"text":673,"config":674},"Terms of use",{"href":675,"dataGaName":676,"dataGaLocation":498},"/terms/","terms of use",{"text":678,"config":679},"Privacy statement",{"href":680,"dataGaName":681,"dataGaLocation":498},"/privacy/","privacy statement",{"text":683,"config":684},"Cookie preferences",{"dataGaName":685,"dataGaLocation":498,"id":686,"isOneTrustButton":36},"cookie preferences","ot-sdk-btn",{"items":688},[689,691,693],{"text":673,"config":690},{"href":675,"dataGaName":676,"dataGaLocation":498},{"text":678,"config":692},{"href":680,"dataGaName":681,"dataGaLocation":498},{"text":683,"config":694},{"dataGaName":685,"dataGaLocation":498,"id":686,"isOneTrustButton":36},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[700,712],{"_path":701,"_dir":702,"_draft":6,"_partial":6,"_locale":7,"content":703,"config":707,"_id":709,"_type":39,"title":18,"_source":41,"_file":710,"_stem":711,"_extension":44},"/en-us/blog/authors/chance-feick","authors",{"name":18,"config":704},{"headshot":705,"ctfId":706},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666442/Blog/Author%20Headshots/chance_feick_headshot.png","18dtRbXV47xqf5iDrOIduM",{"template":708},"BlogAuthor","content:en-us:blog:authors:chance-feick.yml","en-us/blog/authors/chance-feick.yml","en-us/blog/authors/chance-feick",{"_path":713,"_dir":702,"_draft":6,"_partial":6,"_locale":7,"content":714,"config":718,"_id":719,"_type":39,"title":19,"_source":41,"_file":720,"_stem":721,"_extension":44},"/en-us/blog/authors/sam-wiskow",{"name":19,"config":715},{"headshot":716,"ctfId":717},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659433/Blog/Author%20Headshots/swiskow-headshot.jpg","swiskow",{"template":708},"content:en-us:blog:authors:sam-wiskow.yml","en-us/blog/authors/sam-wiskow.yml","en-us/blog/authors/sam-wiskow",{"_path":723,"_dir":47,"_draft":6,"_partial":6,"_locale":7,"header":724,"eyebrow":725,"blurb":726,"button":727,"secondaryButton":731,"_id":733,"_type":39,"title":734,"_source":41,"_file":735,"_stem":736,"_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":728},{"href":729,"dataGaName":58,"dataGaLocation":730},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":60,"config":732},{"href":62,"dataGaName":63,"dataGaLocation":730},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1758326223114]