[{"data":1,"prerenderedAt":704},["ShallowReactive",2],{"/en-us/blog/path-to-decomposing-gitlab-database-part2/":3,"navigation-en-us":36,"banner-en-us":453,"footer-en-us":465,"Dylan Griffith":676,"next-steps-en-us":689},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":26,"_id":29,"_type":30,"title":31,"_source":32,"_file":33,"_stem":34,"_extension":35},"/en-us/blog/path-to-decomposing-gitlab-database-part2","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"GitLab database decomposition: Final migration and results","This is the second in our three-part technical summary of the yearlong project to decompose GitLab's Postgres database.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663397/Blog/Hero%20Images/logoforblogpost.jpg","https://about.gitlab.com/blog/path-to-decomposing-gitlab-database-part2","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Decomposing the GitLab backend database, Part 2: Final migration and results\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dylan Griffith\"}],\n        \"datePublished\": \"2022-08-04\",\n      }",{"title":17,"description":10,"authors":18,"heroImage":11,"date":20,"body":21,"category":22,"tags":23},"Decomposing the GitLab backend database, Part 2: Final migration and results",[19],"Dylan Griffith","2022-08-04","\n\n_This blog post is part 2 in a three-part series about decomposing the GitLab backend database. It focuses on the final migration\nprocess and highlights the results we achieved after the migration. If you want to read about the design and planning phase, check out [part 1](/blog/path-to-decomposing-gitlab-database-part1/)._\n\n## Deciding between zero downtime and full downtime\n\nEarly on in the project we thought it would be necessary for the migration to\nbe \"zero downtime\" or \"near-zero downtime\". We [came up with this plan][initial_migration_plan_mr]\nearly on which involved (in summary):\n1. The entire database would be replicated (including non-CI tables) using\n   Patroni cascading/standby replication to a dedicated CI Patroni cluster.\n   Replication only lags by at most a few seconds.\n2. Read traffic for CI tables could be split ahead of time to read from the CI\n   replicas.\n3. Write traffic would be split ahead of the migration into CI and Main by\n   sending these through separate dedicated PGBouncer proxies. Initially CI\n   writes still go to the Main database since the CI cluster is just a standby.\n   These proxies would be the thing we reconfigured during the live migration\n   to point at the CI cluster.\n4. At the time of migration we would pause writes to the CI tables by pausing\n   the CI PGBouncer.\n5. After pausing writes to the CI database we'd capture the current LSN\n   position in Postgres of the Main primary database (now expect no more writes\n   to CI tables to be possible).\n6. After that we wait until the CI database replication catches up to that\n   point.\n7. Then we promote the CI database to accept writes (remove the cascading\n   replication).\n8. Then we reconfigure writes to point to the CI database by updating the write\n   host in the CI PGBouncer.\n9. The migration is done.\n\n![Database architecture actual final migration step](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/phase4to7.png)\n\nThis approach (assuming that the CI replicas were only delayed by a few\nseconds) would mean that, at most, there would be a few seconds where CI writes\nmight result in errors and 500s for users. Many failures would likely already\nbe retried since much of CI write traffic goes via asynchronous (Sidekiq)\nprocesses that automatically retry.\n\nIn the end we didn't use this approach because:\n\n1. This approach didn't have an easy-to-implement rollback strategy. Data that\n   was written to CI tables during the migration would be lost if we rolled\n   back to just the Main database.\n2. The period of a few seconds where we expect to see some errors might make it\n   difficult for us to quickly determine the success or failure of the\n   migration.\n3. There was no hard business requirement to avoid downtime.\n\nThe [migration approach we ended up using][phase7_summary_epic] took two\nhours of downtime. We stopped all GitLab services that could read or write\nfrom the database. We also blocked user-level traffic at the CDN (Cloudflare) to allow us\nto do some automated and manual testing before opening traffic back up to\nusers. This allowed us to prepare a [slightly more straightforward rollback procedure][rollback_issue],\nwhich was:\n\n1. Reconfigure all read-only CI traffic back to the Main replicas\n2. Reconfigure all read-write CI traffic (via PGBouncer) back to the Main\n   primary database\n3. Increment the Postgres sequences for all CI tables to avoid overlapping with\n   data we created in our testing\n\nUltimately having a simple rollback mechanism proved very useful in doing many\npractice runs on staging.\n\n## Rehearsing the migration process\n\nBefore executing the final migration on GitLab.com, we executed seven rehearsals\nwith rollback and one final migration on our staging environment. In these\npractice runs, we discovered many small issues that would have likely caused\nissues in the production environment.\n\nThese rehearsals also gave all the participants an opportunity to perfect their steps\nin the process to minimize delays in our production rollout. This practice\nultimately allowed us to be quite confident in our timeline of at most two hours of downtime.\n\nIn the end, we finished the migration in 93 minutes, with a few small delays caused by\nsurprises we did not see in staging.\n\nThe rehearsal process was very time-consuming and a vast effort to execute in\nthe context of GitLab, where we all [work\nasynchronously](https://about.gitlab.com/company/culture/all-remote/asynchronous/)\nand across different timezones. However, it proved to be essential to the success of\nthis project.\n\n## Preparing for production migration\n\nOne week before our the final migration on production we prepared a production\nreadiness review issue for final approval from executives. This was a good\nopportunity to highlight all the preparation and validation we'd done to give\nus confidence in the plan. This also encouraged us to do extra validation where\nwe might expect to see questions or concerns about the plan.\n\nSome highlights from this review included:\n\n1. The amount of practice runs we'd done including details about the problems\n   we'd seen and resolved in staging\n2. Metrics which we'd observed to prove all the queries were using the right\n   database connections already\n3. Details about how long we'd been running without issues in local development\n   with all GitLab developers running with two databases by default\n4. Details about the rollback strategy we would use if necessary and how we\n   tested this rollback strategy in staging as well as some production\n   validation\n\n## Tracking the results\n\nAfter we completed the rollout we tracked\n[performance improvements across some metrics we expected to improve][performance_improvements_tracking_issue].\n\nThe data showed:\n\n- We decreased the CPU utilization of our primary database server, giving us much more headroom.\n\n  ![CPU peaks before and after decomposition shows smaller peaks after](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/cpu-post-decomposition-improvement.png)\n\n- We can free around 9.2TiB out of 22TiB from our Main database by truncating the CI tables.\n- We can free around 12.5TiB out of 22TiB from our CI database by truncating the Main tables.\n- We significantly reduced the rate of dead tuples on our Main database.\n- We significantly reduced vacuuming saturation. Before decomposition the Main database\n  maximum vacuuming saturation was up to 100%, with the average closer to 80%. After\n  decomposition, vacuuming saturation has stabilized at around 15% for\n  both databases.\n\n  ![Vacuum saturation before and after decomposition shows a decrease after decomposition](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/vacuum-saturation-post-decomposition.png)\n\n- We reduced the average query duration for our Sidekiq PGBouncer query\n  pool by at least a factor of 5 once we scaled up connection limits due to our\n  increased headroom. Previously we needed to throttle connections for\n  asynchronous workloads to avoid overloading the primary database.\n\n  ![Average active query duration by workload shows a decrease after scaling connections after decomposition](https://about.gitlab.com/images/blogimages/2022-07-15-path-to-decomposing-gitlab-database/pgbouncer-active-query-duration-by-workload.png)\n\n## Continue reading\n\nYou can read more about some interesting technical challenges and surprises we\nhad to deal with along the way in\n[part 3](/blog/path-to-decomposing-gitlab-database-part3/).\n\n[initial_migration_plan_mr]: https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/84588\n[performance_improvements_tracking_issue]: https://gitlab.com/gl-retrospectives/sharding-group/-/issues/18\n[phase7_summary_epic]: https://gitlab.com/groups/gitlab-org/-/epics/7791\n[rollback_issue]: https://gitlab.com/gitlab-org/gitlab/-/issues/361759\n","engineering",[24,25],"inside GitLab","design",{"slug":27,"featured":6,"template":28},"path-to-decomposing-gitlab-database-part2","BlogPost","content:en-us:blog:path-to-decomposing-gitlab-database-part2.yml","yaml","Path To Decomposing Gitlab Database Part2","content","en-us/blog/path-to-decomposing-gitlab-database-part2.yml","en-us/blog/path-to-decomposing-gitlab-database-part2","yml",{"_path":37,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":39,"_id":449,"_type":30,"title":450,"_source":32,"_file":451,"_stem":452,"_extension":35},"/shared/en-us/main-navigation","en-us",{"logo":40,"freeTrial":45,"sales":50,"login":55,"items":60,"search":390,"minimal":421,"duo":440},{"config":41},{"href":42,"dataGaName":43,"dataGaLocation":44},"/","gitlab logo","header",{"text":46,"config":47},"Get free trial",{"href":48,"dataGaName":49,"dataGaLocation":44},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":51,"config":52},"Talk to sales",{"href":53,"dataGaName":54,"dataGaLocation":44},"/sales/","sales",{"text":56,"config":57},"Sign in",{"href":58,"dataGaName":59,"dataGaLocation":44},"https://gitlab.com/users/sign_in/","sign in",[61,105,201,206,311,371],{"text":62,"config":63,"cards":65,"footer":88},"Platform",{"dataNavLevelOne":64},"platform",[66,72,80],{"title":62,"description":67,"link":68},"The most comprehensive AI-powered DevSecOps Platform",{"text":69,"config":70},"Explore our Platform",{"href":71,"dataGaName":64,"dataGaLocation":44},"/platform/",{"title":73,"description":74,"link":75},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":76,"config":77},"Meet GitLab Duo",{"href":78,"dataGaName":79,"dataGaLocation":44},"/gitlab-duo/","gitlab duo ai",{"title":81,"description":82,"link":83},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":84,"config":85},"Learn more",{"href":86,"dataGaName":87,"dataGaLocation":44},"/why-gitlab/","why gitlab",{"title":89,"items":90},"Get started with",[91,96,101],{"text":92,"config":93},"Platform Engineering",{"href":94,"dataGaName":95,"dataGaLocation":44},"/solutions/platform-engineering/","platform engineering",{"text":97,"config":98},"Developer Experience",{"href":99,"dataGaName":100,"dataGaLocation":44},"/developer-experience/","Developer experience",{"text":102,"config":103},"MLOps",{"href":104,"dataGaName":102,"dataGaLocation":44},"/topics/devops/the-role-of-ai-in-devops/",{"text":106,"left":107,"config":108,"link":110,"lists":114,"footer":183},"Product",true,{"dataNavLevelOne":109},"solutions",{"text":111,"config":112},"View all Solutions",{"href":113,"dataGaName":109,"dataGaLocation":44},"/solutions/",[115,140,162],{"title":116,"description":117,"link":118,"items":123},"Automation","CI/CD and automation to accelerate deployment",{"config":119},{"icon":120,"href":121,"dataGaName":122,"dataGaLocation":44},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[124,128,132,136],{"text":125,"config":126},"CI/CD",{"href":127,"dataGaLocation":44,"dataGaName":125},"/solutions/continuous-integration/",{"text":129,"config":130},"AI-Assisted Development",{"href":78,"dataGaLocation":44,"dataGaName":131},"AI assisted development",{"text":133,"config":134},"Source Code Management",{"href":135,"dataGaLocation":44,"dataGaName":133},"/solutions/source-code-management/",{"text":137,"config":138},"Automated Software Delivery",{"href":121,"dataGaLocation":44,"dataGaName":139},"Automated software delivery",{"title":141,"description":142,"link":143,"items":148},"Security","Deliver code faster without compromising security",{"config":144},{"href":145,"dataGaName":146,"dataGaLocation":44,"icon":147},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[149,152,157],{"text":150,"config":151},"Security & Compliance",{"href":145,"dataGaLocation":44,"dataGaName":150},{"text":153,"config":154},"Software Supply Chain Security",{"href":155,"dataGaLocation":44,"dataGaName":156},"/solutions/supply-chain/","Software supply chain security",{"text":158,"config":159},"Compliance & Governance",{"href":160,"dataGaLocation":44,"dataGaName":161},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":163,"link":164,"items":169},"Measurement",{"config":165},{"icon":166,"href":167,"dataGaName":168,"dataGaLocation":44},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[170,174,178],{"text":171,"config":172},"Visibility & Measurement",{"href":167,"dataGaLocation":44,"dataGaName":173},"Visibility and Measurement",{"text":175,"config":176},"Value Stream Management",{"href":177,"dataGaLocation":44,"dataGaName":175},"/solutions/value-stream-management/",{"text":179,"config":180},"Analytics & Insights",{"href":181,"dataGaLocation":44,"dataGaName":182},"/solutions/analytics-and-insights/","Analytics and insights",{"title":184,"items":185},"GitLab for",[186,191,196],{"text":187,"config":188},"Enterprise",{"href":189,"dataGaLocation":44,"dataGaName":190},"/enterprise/","enterprise",{"text":192,"config":193},"Small Business",{"href":194,"dataGaLocation":44,"dataGaName":195},"/small-business/","small business",{"text":197,"config":198},"Public Sector",{"href":199,"dataGaLocation":44,"dataGaName":200},"/solutions/public-sector/","public sector",{"text":202,"config":203},"Pricing",{"href":204,"dataGaName":205,"dataGaLocation":44,"dataNavLevelOne":205},"/pricing/","pricing",{"text":207,"config":208,"link":210,"lists":214,"feature":298},"Resources",{"dataNavLevelOne":209},"resources",{"text":211,"config":212},"View all resources",{"href":213,"dataGaName":209,"dataGaLocation":44},"/resources/",[215,248,270],{"title":216,"items":217},"Getting started",[218,223,228,233,238,243],{"text":219,"config":220},"Install",{"href":221,"dataGaName":222,"dataGaLocation":44},"/install/","install",{"text":224,"config":225},"Quick start guides",{"href":226,"dataGaName":227,"dataGaLocation":44},"/get-started/","quick setup checklists",{"text":229,"config":230},"Learn",{"href":231,"dataGaLocation":44,"dataGaName":232},"https://university.gitlab.com/","learn",{"text":234,"config":235},"Product documentation",{"href":236,"dataGaName":237,"dataGaLocation":44},"https://docs.gitlab.com/","product documentation",{"text":239,"config":240},"Best practice videos",{"href":241,"dataGaName":242,"dataGaLocation":44},"/getting-started-videos/","best practice videos",{"text":244,"config":245},"Integrations",{"href":246,"dataGaName":247,"dataGaLocation":44},"/integrations/","integrations",{"title":249,"items":250},"Discover",[251,256,260,265],{"text":252,"config":253},"Customer success stories",{"href":254,"dataGaName":255,"dataGaLocation":44},"/customers/","customer success stories",{"text":257,"config":258},"Blog",{"href":259,"dataGaName":5,"dataGaLocation":44},"/blog/",{"text":261,"config":262},"Remote",{"href":263,"dataGaName":264,"dataGaLocation":44},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":266,"config":267},"TeamOps",{"href":268,"dataGaName":269,"dataGaLocation":44},"/teamops/","teamops",{"title":271,"items":272},"Connect",[273,278,283,288,293],{"text":274,"config":275},"GitLab Services",{"href":276,"dataGaName":277,"dataGaLocation":44},"/services/","services",{"text":279,"config":280},"Community",{"href":281,"dataGaName":282,"dataGaLocation":44},"/community/","community",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":44},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":44},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":44},"/partners/","partners",{"backgroundColor":299,"textColor":300,"text":301,"image":302,"link":306},"#2f2a6b","#fff","Insights for the future of software development",{"altText":303,"config":304},"the source promo card",{"src":305},"/images/navigation/the-source-promo-card.svg",{"text":307,"config":308},"Read the latest",{"href":309,"dataGaName":310,"dataGaLocation":44},"/the-source/","the source",{"text":312,"config":313,"lists":315},"Company",{"dataNavLevelOne":314},"company",[316],{"items":317},[318,323,329,331,336,341,346,351,356,361,366],{"text":319,"config":320},"About",{"href":321,"dataGaName":322,"dataGaLocation":44},"/company/","about",{"text":324,"config":325,"footerGa":328},"Jobs",{"href":326,"dataGaName":327,"dataGaLocation":44},"/jobs/","jobs",{"dataGaName":327},{"text":289,"config":330},{"href":291,"dataGaName":292,"dataGaLocation":44},{"text":332,"config":333},"Leadership",{"href":334,"dataGaName":335,"dataGaLocation":44},"/company/team/e-group/","leadership",{"text":337,"config":338},"Team",{"href":339,"dataGaName":340,"dataGaLocation":44},"/company/team/","team",{"text":342,"config":343},"Handbook",{"href":344,"dataGaName":345,"dataGaLocation":44},"https://handbook.gitlab.com/","handbook",{"text":347,"config":348},"Investor relations",{"href":349,"dataGaName":350,"dataGaLocation":44},"https://ir.gitlab.com/","investor relations",{"text":352,"config":353},"Trust Center",{"href":354,"dataGaName":355,"dataGaLocation":44},"/security/","trust center",{"text":357,"config":358},"AI Transparency Center",{"href":359,"dataGaName":360,"dataGaLocation":44},"/ai-transparency-center/","ai transparency center",{"text":362,"config":363},"Newsletter",{"href":364,"dataGaName":365,"dataGaLocation":44},"/company/contact/","newsletter",{"text":367,"config":368},"Press",{"href":369,"dataGaName":370,"dataGaLocation":44},"/press/","press",{"text":372,"config":373,"lists":374},"Contact us",{"dataNavLevelOne":314},[375],{"items":376},[377,380,385],{"text":51,"config":378},{"href":53,"dataGaName":379,"dataGaLocation":44},"talk to sales",{"text":381,"config":382},"Get help",{"href":383,"dataGaName":384,"dataGaLocation":44},"/support/","get help",{"text":386,"config":387},"Customer portal",{"href":388,"dataGaName":389,"dataGaLocation":44},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":391,"login":392,"suggestions":399},"Close",{"text":393,"link":394},"To search repositories and projects, login to",{"text":395,"config":396},"gitlab.com",{"href":58,"dataGaName":397,"dataGaLocation":398},"search login","search",{"text":400,"default":401},"Suggestions",[402,404,408,410,414,418],{"text":73,"config":403},{"href":78,"dataGaName":73,"dataGaLocation":398},{"text":405,"config":406},"Code Suggestions (AI)",{"href":407,"dataGaName":405,"dataGaLocation":398},"/solutions/code-suggestions/",{"text":125,"config":409},{"href":127,"dataGaName":125,"dataGaLocation":398},{"text":411,"config":412},"GitLab on AWS",{"href":413,"dataGaName":411,"dataGaLocation":398},"/partners/technology-partners/aws/",{"text":415,"config":416},"GitLab on Google Cloud",{"href":417,"dataGaName":415,"dataGaLocation":398},"/partners/technology-partners/google-cloud-platform/",{"text":419,"config":420},"Why GitLab?",{"href":86,"dataGaName":419,"dataGaLocation":398},{"freeTrial":422,"mobileIcon":427,"desktopIcon":432,"secondaryButton":435},{"text":423,"config":424},"Start free trial",{"href":425,"dataGaName":49,"dataGaLocation":426},"https://gitlab.com/-/trials/new/","nav",{"altText":428,"config":429},"Gitlab Icon",{"src":430,"dataGaName":431,"dataGaLocation":426},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":428,"config":433},{"src":434,"dataGaName":431,"dataGaLocation":426},"/images/brand/gitlab-logo-type.svg",{"text":436,"config":437},"Get Started",{"href":438,"dataGaName":439,"dataGaLocation":426},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":441,"mobileIcon":445,"desktopIcon":447},{"text":442,"config":443},"Learn more about GitLab Duo",{"href":78,"dataGaName":444,"dataGaLocation":426},"gitlab duo",{"altText":428,"config":446},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":448},{"src":434,"dataGaName":431,"dataGaLocation":426},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":454,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"title":455,"button":456,"config":460,"_id":462,"_type":30,"_source":32,"_file":463,"_stem":464,"_extension":35},"/shared/en-us/banner","GitLab Duo Agent Platform is now in public beta!",{"text":84,"config":457},{"href":458,"dataGaName":459,"dataGaLocation":44},"/gitlab-duo/agent-platform/","duo banner",{"layout":461},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":466,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":467,"_id":672,"_type":30,"title":673,"_source":32,"_file":674,"_stem":675,"_extension":35},"/shared/en-us/main-footer",{"text":468,"source":469,"edit":475,"contribute":480,"config":485,"items":490,"minimal":664},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":470,"config":471},"View page source",{"href":472,"dataGaName":473,"dataGaLocation":474},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":476,"config":477},"Edit this page",{"href":478,"dataGaName":479,"dataGaLocation":474},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":481,"config":482},"Please contribute",{"href":483,"dataGaName":484,"dataGaLocation":474},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":486,"facebook":487,"youtube":488,"linkedin":489},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[491,514,571,600,634],{"title":62,"links":492,"subMenu":497},[493],{"text":494,"config":495},"DevSecOps platform",{"href":71,"dataGaName":496,"dataGaLocation":474},"devsecops platform",[498],{"title":202,"links":499},[500,504,509],{"text":501,"config":502},"View plans",{"href":204,"dataGaName":503,"dataGaLocation":474},"view plans",{"text":505,"config":506},"Why Premium?",{"href":507,"dataGaName":508,"dataGaLocation":474},"/pricing/premium/","why premium",{"text":510,"config":511},"Why Ultimate?",{"href":512,"dataGaName":513,"dataGaLocation":474},"/pricing/ultimate/","why ultimate",{"title":515,"links":516},"Solutions",[517,522,525,527,532,537,541,544,548,553,555,558,561,566],{"text":518,"config":519},"Digital transformation",{"href":520,"dataGaName":521,"dataGaLocation":474},"/topics/digital-transformation/","digital transformation",{"text":150,"config":523},{"href":145,"dataGaName":524,"dataGaLocation":474},"security & compliance",{"text":139,"config":526},{"href":121,"dataGaName":122,"dataGaLocation":474},{"text":528,"config":529},"Agile development",{"href":530,"dataGaName":531,"dataGaLocation":474},"/solutions/agile-delivery/","agile delivery",{"text":533,"config":534},"Cloud transformation",{"href":535,"dataGaName":536,"dataGaLocation":474},"/topics/cloud-native/","cloud transformation",{"text":538,"config":539},"SCM",{"href":135,"dataGaName":540,"dataGaLocation":474},"source code management",{"text":125,"config":542},{"href":127,"dataGaName":543,"dataGaLocation":474},"continuous integration & delivery",{"text":545,"config":546},"Value stream management",{"href":177,"dataGaName":547,"dataGaLocation":474},"value stream management",{"text":549,"config":550},"GitOps",{"href":551,"dataGaName":552,"dataGaLocation":474},"/solutions/gitops/","gitops",{"text":187,"config":554},{"href":189,"dataGaName":190,"dataGaLocation":474},{"text":556,"config":557},"Small business",{"href":194,"dataGaName":195,"dataGaLocation":474},{"text":559,"config":560},"Public sector",{"href":199,"dataGaName":200,"dataGaLocation":474},{"text":562,"config":563},"Education",{"href":564,"dataGaName":565,"dataGaLocation":474},"/solutions/education/","education",{"text":567,"config":568},"Financial services",{"href":569,"dataGaName":570,"dataGaLocation":474},"/solutions/finance/","financial services",{"title":207,"links":572},[573,575,577,579,582,584,586,588,590,592,594,596,598],{"text":219,"config":574},{"href":221,"dataGaName":222,"dataGaLocation":474},{"text":224,"config":576},{"href":226,"dataGaName":227,"dataGaLocation":474},{"text":229,"config":578},{"href":231,"dataGaName":232,"dataGaLocation":474},{"text":234,"config":580},{"href":236,"dataGaName":581,"dataGaLocation":474},"docs",{"text":257,"config":583},{"href":259,"dataGaName":5,"dataGaLocation":474},{"text":252,"config":585},{"href":254,"dataGaName":255,"dataGaLocation":474},{"text":261,"config":587},{"href":263,"dataGaName":264,"dataGaLocation":474},{"text":274,"config":589},{"href":276,"dataGaName":277,"dataGaLocation":474},{"text":266,"config":591},{"href":268,"dataGaName":269,"dataGaLocation":474},{"text":279,"config":593},{"href":281,"dataGaName":282,"dataGaLocation":474},{"text":284,"config":595},{"href":286,"dataGaName":287,"dataGaLocation":474},{"text":289,"config":597},{"href":291,"dataGaName":292,"dataGaLocation":474},{"text":294,"config":599},{"href":296,"dataGaName":297,"dataGaLocation":474},{"title":312,"links":601},[602,604,606,608,610,612,614,618,623,625,627,629],{"text":319,"config":603},{"href":321,"dataGaName":314,"dataGaLocation":474},{"text":324,"config":605},{"href":326,"dataGaName":327,"dataGaLocation":474},{"text":332,"config":607},{"href":334,"dataGaName":335,"dataGaLocation":474},{"text":337,"config":609},{"href":339,"dataGaName":340,"dataGaLocation":474},{"text":342,"config":611},{"href":344,"dataGaName":345,"dataGaLocation":474},{"text":347,"config":613},{"href":349,"dataGaName":350,"dataGaLocation":474},{"text":615,"config":616},"Sustainability",{"href":617,"dataGaName":615,"dataGaLocation":474},"/sustainability/",{"text":619,"config":620},"Diversity, inclusion and belonging (DIB)",{"href":621,"dataGaName":622,"dataGaLocation":474},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":352,"config":624},{"href":354,"dataGaName":355,"dataGaLocation":474},{"text":362,"config":626},{"href":364,"dataGaName":365,"dataGaLocation":474},{"text":367,"config":628},{"href":369,"dataGaName":370,"dataGaLocation":474},{"text":630,"config":631},"Modern Slavery Transparency Statement",{"href":632,"dataGaName":633,"dataGaLocation":474},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":635,"links":636},"Contact Us",[637,640,642,644,649,654,659],{"text":638,"config":639},"Contact an expert",{"href":53,"dataGaName":54,"dataGaLocation":474},{"text":381,"config":641},{"href":383,"dataGaName":384,"dataGaLocation":474},{"text":386,"config":643},{"href":388,"dataGaName":389,"dataGaLocation":474},{"text":645,"config":646},"Status",{"href":647,"dataGaName":648,"dataGaLocation":474},"https://status.gitlab.com/","status",{"text":650,"config":651},"Terms of use",{"href":652,"dataGaName":653,"dataGaLocation":474},"/terms/","terms of use",{"text":655,"config":656},"Privacy statement",{"href":657,"dataGaName":658,"dataGaLocation":474},"/privacy/","privacy statement",{"text":660,"config":661},"Cookie preferences",{"dataGaName":662,"dataGaLocation":474,"id":663,"isOneTrustButton":107},"cookie preferences","ot-sdk-btn",{"items":665},[666,668,670],{"text":650,"config":667},{"href":652,"dataGaName":653,"dataGaLocation":474},{"text":655,"config":669},{"href":657,"dataGaName":658,"dataGaLocation":474},{"text":660,"config":671},{"dataGaName":662,"dataGaLocation":474,"id":663,"isOneTrustButton":107},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[677],{"_path":678,"_dir":679,"_draft":6,"_partial":6,"_locale":7,"content":680,"config":684,"_id":686,"_type":30,"title":19,"_source":32,"_file":687,"_stem":688,"_extension":35},"/en-us/blog/authors/dylan-griffith","authors",{"name":19,"config":681},{"headshot":682,"ctfId":683},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672822/Blog/Author%20Headshots/DylanGriffith-headshot.jpg","DylanGriffith",{"template":685},"BlogAuthor","content:en-us:blog:authors:dylan-griffith.yml","en-us/blog/authors/dylan-griffith.yml","en-us/blog/authors/dylan-griffith",{"_path":690,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"header":691,"eyebrow":692,"blurb":693,"button":694,"secondaryButton":698,"_id":700,"_type":30,"title":701,"_source":32,"_file":702,"_stem":703,"_extension":35},"/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":46,"config":695},{"href":696,"dataGaName":49,"dataGaLocation":697},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":51,"config":699},{"href":53,"dataGaName":54,"dataGaLocation":697},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1753475351150]