[{"data":1,"prerenderedAt":1218},["ShallowReactive",2],{"/blog/using-run-parallel-jobs":3,"navigation-en-us":431,"banner-en-us":859,"footer-en-us":869,"blog-post-authors-en-us-Miguel Rincon":1114,"blog-related-posts-en-us-using-run-parallel-jobs":1128,"blog-promotions-en-us":1154,"next-steps-en-us":1208},{"id":4,"title":5,"authors":6,"body":8,"category":407,"date":408,"description":409,"extension":410,"externalUrl":411,"faq":411,"featured":412,"heroImage":413,"meta":414,"navigation":415,"path":416,"seo":417,"slug":421,"stem":422,"tags":423,"template":429,"updatedDate":411,"__hash__":430},"blogPosts/en-us/blog/using-run-parallel-jobs.md","How we used parallel CI/CD jobs to increase our productivity",[7],"Miguel Rincon",{"type":9,"value":10,"toc":400},"minimark",[11,15,18,28,37,45,59,64,79,97,100,107,110,113,117,128,134,181,186,229,241,244,251,258,272,275,282,286,289,298,302,308,328,332,335,348,351,379,382,396],[12,13,14],"p",{},"At GitLab, we must verify simultaneous changes from the hundreds of people that contribute to GitLab each day. How can we help them contribute efficiently using our pipelines?",[12,16,17],{},"The pipelines that we use to build and verify GitLab have more than 90 jobs. Not all of those jobs are equal. Some are simple tasks that take a few seconds to finish, while others are long-running processes that must be optimized carefully.",[12,19,20,21,27],{},"At the time of this writing, we have more than 700 ",[22,23,26],"a",{"href":24,"rel":25},"https://gitlab.com/gitlab-org/gitlab/-/pipelines?page=1&scope=all&status=running",[],"pipelines running",". Each of these pipelines represent changes from team members and contributors from the wider community. All GitLab contributors must wait for the pipelines to finish to make sure the change works and integrates with the rest of the product. We want our pipelines to finish as fast as possible to maintain the productivity of our teams.",[12,29,30,31,36],{},"This is why we constantly monitor the duration of our pipelines. For example, in December 2020, successful merge request pipelines had a duration of ",[22,32,35],{"href":33,"rel":34},"https://handbook.gitlab.com/handbook/engineering/performance/#average-merge-request-pipeline-duration-for-gitlab",[],"53.8 minutes",":",[12,38,39,44],{},[40,41],"img",{"alt":42,"src":43},"Average pipeline duration was 53.8 minutes in December","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782399262/blog/Content%20Images/using-run-parallel-jobs/historical-pipeline-duration.png","\nThe average pipeline took 53.8 minutes to finish in December.",[12,46,47,48,53,54,58],{},"Given that we run ",[22,49,52],{"href":50,"rel":51},"https://gitlab.com/gitlab-org/gitlab/-/pipelines/charts",[],"around 500 merge request pipelines"," per day, we want to know: Can we optimize our process to change how long-running jobs ",[55,56,57],"em",{},"run","?",[60,61,63],"h2",{"id":62},"how-we-fixed-our-bottleneck-jobs-by-making-them-run-in-parallel","How we fixed our bottleneck jobs by making them run in parallel",[12,65,66,67,71,72,75,76,78],{},"The ",[68,69,70],"code",{},"frontend-fixtures"," job uses ",[68,73,74],{},"rspec"," to generate mock data files, which are then saved as files called \"fixtures\". These files are loaded by our frontend tests, so the ",[68,77,70],{}," must finish before any of our frontend tests can start.",[80,81,82],"blockquote",{},[12,83,84,85,93,94,96],{},"As not all of our tests need these frontend fixtures, many jobs use the ",[22,86,89,92],{"href":87,"rel":88},"https://docs.gitlab.com/ci/yaml/#needs",[],[68,90,91],{},"needs"," keyword"," to start before the ",[68,95,70],{}," job is done.",[12,98,99],{},"In our pipelines, this job looked like this:",[12,101,102,106],{},[40,103],{"alt":104,"src":105},"The frontend-fixtures job","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782399261/blog/Content%20Images/using-run-parallel-jobs/fixtures-job.png","\nInside the frontend fixtures job.",[12,108,109],{},"This job had a normal duration of 20 minutes, and each individual fixture could be generated independently, so we knew there was an opportunity to run this process in parallel.",[12,111,112],{},"The next step was to configure our pipeline to split the job into multiple batches that could be run in parallel.",[60,114,116],{"id":115},"how-to-make-frontend-fixtures-a-parallel-job","How to make frontend-fixtures a parallel job",[12,118,119,120,127],{},"Fortunately, GitLab CI provides an easy way to run a job in parallel using the ",[22,121,124,92],{"href":122,"rel":123},"https://docs.gitlab.com/ci/yaml/#parallel",[],[68,125,126],{},"parallel",". In the background, this creates \"clones\" of the same job, so that multiple copies of it can run simultaneously.",[12,129,130],{},[131,132,133],"strong",{},"Before:",[135,136,141],"pre",{"className":137,"code":138,"language":139,"meta":140,"style":140},"language-yml shiki shiki-themes github-light","frontend-fixtures:\n  extends:\n    - .frontend-fixtures-base\n    - .frontend:rules:default-frontend-jobs\n\n","yml","",[68,142,143,155,163,173],{"__ignoreMap":140},[144,145,148,151],"span",{"class":146,"line":147},"line",1,[144,149,70],{"class":150},"shJU0",[144,152,154],{"class":153},"sgsFI",":\n",[144,156,158,161],{"class":146,"line":157},2,[144,159,160],{"class":150},"  extends",[144,162,154],{"class":153},[144,164,166,169],{"class":146,"line":165},3,[144,167,168],{"class":153},"    - ",[144,170,172],{"class":171},"sYBdl",".frontend-fixtures-base\n",[144,174,176,178],{"class":146,"line":175},4,[144,177,168],{"class":153},[144,179,180],{"class":171},".frontend:rules:default-frontend-jobs\n",[12,182,183],{},[131,184,185],{},"After:",[135,187,189],{"className":137,"code":188,"language":139,"meta":140,"style":140},"rspec-ee frontend_fixture:\n  extends:\n    - .frontend-fixtures-base\n    - .frontend:rules:default-frontend-jobs\n  parallel: 2\n\n",[68,190,191,198,204,210,216],{"__ignoreMap":140},[144,192,193,196],{"class":146,"line":147},[144,194,195],{"class":150},"rspec-ee frontend_fixture",[144,197,154],{"class":153},[144,199,200,202],{"class":146,"line":157},[144,201,160],{"class":150},[144,203,154],{"class":153},[144,205,206,208],{"class":146,"line":165},[144,207,168],{"class":153},[144,209,172],{"class":171},[144,211,212,214],{"class":146,"line":175},[144,213,168],{"class":153},[144,215,180],{"class":171},[144,217,219,222,225],{"class":146,"line":218},5,[144,220,221],{"class":150},"  parallel",[144,223,224],{"class":153},": ",[144,226,228],{"class":227},"sYu0t","2\n",[12,230,231,232,237,238,240],{},"You will notice two changes. First, we changed the name of the job, so our job is picked up by ",[22,233,236],{"href":234,"rel":235},"https://docs.knapsackpro.com/ruby/knapsack",[],"Knapsack"," (more on that later), and then we add the keyword ",[68,239,126],{},", so the job gets duplicated and runs in parallel.",[12,242,243],{},"The new jobs that are generated look like this:",[12,245,246,250],{},[40,247],{"alt":248,"src":249},"Our fixtures job running in parallel","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782399261/blog/Content%20Images/using-run-parallel-jobs/fixtures-job-parallel.png","\nThe new jobs that are picked up by Knapsack and run in parallel.",[12,252,253,254,257],{},"As we used a value of ",[68,255,256],{},"parallel: 2",", actually two jobs are generated with the names:",[259,260,261,267],"ul",{},[262,263,264],"li",{},[68,265,266],{},"rspec-ee frontend_fixture 1/2",[262,268,269],{},[68,270,271],{},"rspec-ee frontend_fixture 2/2",[12,273,274],{},"Our two \"generated\" jobs, now take three and 17 minutes respectively, giving us an overall decrease of about three minutes.",[12,276,277,281],{},[40,278],{"alt":279,"src":280},"Two parallel jobs in the pipeline","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782399261/blog/Content%20Images/using-run-parallel-jobs/fixtures-job-detail.png","\nThe parallel jobs that are running in the pipeline.",[60,283,285],{"id":284},"another-way-we-optimized-the-process","Another way we optimized the process",[12,287,288],{},"As we use Knapsack to distribute the test files among the parallel jobs, we were able to make more improvements by reducing the time it takes our longest-running fixtures-generator file to run.",[12,290,291,292,297],{},"We did this by splitting the file into smaller batches and optimizing it, so we have more tests running in parallel, which shaved off an additional ",[22,293,296],{"href":294,"rel":295},"https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47158#note_460372560",[],"~3.5 minutes",".",[60,299,301],{"id":300},"tips-for-running-parallel-jobs","Tips for running parallel jobs",[12,303,304,305,307],{},"If you want to ramp up your productivity you can leverage ",[68,306,126],{}," on your pipelines by following these tips:",[309,310,311,314,322],"ol",{},[262,312,313],{},"Measure the time your pipelines take to run and identify possible bottlenecks to your jobs. You can do this by checking which jobs are slower than others.",[262,315,316,317],{},"Once your slow jobs are identified, try to figure out if they can be run independently from each other or in batches.\n",[259,318,319],{},[262,320,321],{},"Automated tests are usually good candidates, as they tend to be self-contained and run in parallel anyway.",[262,323,324,325,327],{},"Add the ",[68,326,126],{}," keyword, while measuring the outcome over the next few running pipelines.",[60,329,331],{"id":330},"learn-more-about-our-solution","Learn more about our solution",[12,333,334],{},"We discuss how running jobs in parallel improved the speed of pipelines on GitLab Unfiltered.",[336,337,340,341],"figure",{"className":338},[339],"video_container","\n  ",[342,343,347],"iframe",{"src":344,"frameBorder":345,"allowFullScreen":346},"https://www.youtube-nocookie.com/embed/hKsVH_ZhSAk","0","true"," ",[12,349,350],{},"And here are links to some of the resources we used to run pipelines in parallel:",[259,352,353,363,372],{},[262,354,66,355,297],{},[22,356,359,360,362],{"href":357,"rel":358},"https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46959",[],"merge request that introduced ",[68,361,126],{}," to fixtures",[262,364,365,366,371],{},"An important ",[22,367,370],{"href":368,"rel":369},"https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47158",[],"optimization follow-up"," to make one of the slow tests faster.",[262,373,66,374,378],{},[22,375,377],{"href":234,"rel":376},[],"Knapsack gem",", which we leverage to split the tests more evenly in multiple CI nodes.",[12,380,381],{},"And many thanks to Rémy Coutable, who helped me implement this improvement.",[12,383,384,385,390,391],{},"Cover image by ",[22,386,389],{"href":387,"rel":388},"https://unsplash.com/@dustt",[],"@dustt"," on ",[22,392,395],{"href":393,"rel":394},"https://unsplash.com/photos/ZqBNb7xK5s8",[],"Unsplash",[397,398,399],"style",{},"html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}",{"title":140,"searchDepth":157,"depth":157,"links":401},[402,403,404,405,406],{"id":62,"depth":157,"text":63},{"id":115,"depth":157,"text":116},{"id":284,"depth":157,"text":285},{"id":300,"depth":157,"text":301},{"id":330,"depth":157,"text":331},"engineering","2021-01-20","GitLab uses parallel jobs to help long-running jobs run faster.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666717/Blog/Hero%20Images/cover-image.jpg",{},true,"/en-us/blog/using-run-parallel-jobs",{"title":5,"description":409,"ogTitle":5,"ogDescription":409,"noIndex":412,"ogImage":413,"ogUrl":418,"ogSiteName":419,"ogType":420,"canonicalUrls":418},"https://about.gitlab.com/blog/using-run-parallel-jobs","https://about.gitlab.com","article","using-run-parallel-jobs","en-us/blog/using-run-parallel-jobs",[424,425,426,427,428],"inside GitLab","CI","CD","performance","workflow","BlogPost","95YssbqRKERW3oDfLfUiJEPZa6suziYX7S_VEti563A",{"logo":432,"freeTrial":437,"sales":442,"login":447,"items":452,"search":779,"minimal":810,"duo":829,"switchNav":838,"pricingDeployment":849},{"config":433},{"href":434,"dataGaName":435,"dataGaLocation":436},"/","gitlab logo","header",{"text":438,"config":439},"Get free trial",{"href":440,"dataGaName":441,"dataGaLocation":436},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":443,"config":444},"Request a demo",{"href":445,"dataGaName":446,"dataGaLocation":436},"/sales/?contact-topic=request-demo","sales",{"text":448,"config":449},"Sign in",{"href":450,"dataGaName":451,"dataGaLocation":436},"https://gitlab.com/users/sign_in/","sign in",[453,482,582,587,701,757],{"text":454,"config":455,"menu":457},"Platform",{"dataNavLevelOne":456},"platform",{"type":458,"columns":459},"cards",[460,466,474],{"title":454,"description":461,"link":462},"The intelligent orchestration platform for DevSecOps",{"text":463,"config":464},"Explore our Platform",{"href":465,"dataGaName":456,"dataGaLocation":436},"/platform/",{"title":467,"description":468,"link":469},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":470,"config":471},"Meet GitLab Duo",{"href":472,"dataGaName":473,"dataGaLocation":436},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":475,"description":476,"link":477},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":478,"config":479},"Learn more",{"href":480,"dataGaName":481,"dataGaLocation":436},"/why-gitlab/","why gitlab",{"text":483,"left":415,"config":484,"menu":486},"Product",{"dataNavLevelOne":485},"solutions",{"type":487,"link":488,"columns":492,"feature":561},"lists",{"text":489,"config":490},"View all Solutions",{"href":491,"dataGaName":485,"dataGaLocation":436},"/solutions/",[493,517,540],{"title":494,"description":495,"link":496,"items":501},"Automation","CI/CD and automation to accelerate deployment",{"config":497},{"icon":498,"href":499,"dataGaName":500,"dataGaLocation":436},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[502,506,509,513],{"text":503,"config":504},"CI/CD",{"href":505,"dataGaLocation":436,"dataGaName":503},"/solutions/continuous-integration/",{"text":467,"config":507},{"href":472,"dataGaLocation":436,"dataGaName":508},"gitlab duo agent platform - product menu",{"text":510,"config":511},"Source Code Management",{"href":512,"dataGaLocation":436,"dataGaName":510},"/solutions/source-code-management/",{"text":514,"config":515},"Automated Software Delivery",{"href":499,"dataGaLocation":436,"dataGaName":516},"Automated software delivery",{"title":518,"description":519,"link":520,"items":525},"Security","Deliver code faster without compromising security",{"config":521},{"href":522,"dataGaName":523,"dataGaLocation":436,"icon":524},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[526,530,535],{"text":527,"config":528},"Application Security Testing",{"href":522,"dataGaName":529,"dataGaLocation":436},"Application security testing",{"text":531,"config":532},"Software Supply Chain Security",{"href":533,"dataGaLocation":436,"dataGaName":534},"/solutions/supply-chain/","Software supply chain security",{"text":536,"config":537},"Software Compliance",{"href":538,"dataGaName":539,"dataGaLocation":436},"/solutions/software-compliance/","software compliance",{"title":541,"link":542,"items":547},"Measurement",{"config":543},{"icon":544,"href":545,"dataGaName":546,"dataGaLocation":436},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[548,552,556],{"text":549,"config":550},"Visibility & Measurement",{"href":545,"dataGaLocation":436,"dataGaName":551},"Visibility and Measurement",{"text":553,"config":554},"Value Stream Management",{"href":555,"dataGaLocation":436,"dataGaName":553},"/solutions/value-stream-management/",{"text":557,"config":558},"Analytics & Insights",{"href":559,"dataGaLocation":436,"dataGaName":560},"/solutions/analytics-and-insights/","Analytics and insights",{"title":562,"type":487,"items":563},"GitLab for",[564,570,576],{"text":565,"config":566},"Enterprise",{"icon":567,"href":568,"dataGaLocation":436,"dataGaName":569},"Building","/enterprise/","enterprise",{"text":571,"config":572},"Small Business",{"icon":573,"href":574,"dataGaLocation":436,"dataGaName":575},"Work","/small-business/","small business",{"text":577,"config":578},"Public Sector",{"icon":579,"href":580,"dataGaLocation":436,"dataGaName":581},"Organization","/solutions/public-sector/","public sector",{"text":583,"config":584},"Pricing",{"href":585,"dataGaName":586,"dataGaLocation":436,"dataNavLevelOne":586},"/pricing/","pricing",{"text":588,"config":589,"menu":591},"Resources",{"dataNavLevelOne":590},"resources",{"type":487,"link":592,"columns":596,"feature":690},{"text":593,"config":594},"View all resources",{"href":595,"dataGaName":590,"dataGaLocation":436},"/resources/",[597,630,657],{"title":598,"items":599},"Getting started",[600,605,610,615,620,625],{"text":601,"config":602},"Install",{"href":603,"dataGaName":604,"dataGaLocation":436},"/install/","install",{"text":606,"config":607},"Quick start guides",{"href":608,"dataGaName":609,"dataGaLocation":436},"/get-started/","quick setup checklists",{"text":611,"config":612},"Learn",{"href":613,"dataGaLocation":436,"dataGaName":614},"https://university.gitlab.com/","learn",{"text":616,"config":617},"Product documentation",{"href":618,"dataGaName":619,"dataGaLocation":436},"https://docs.gitlab.com/","product documentation",{"text":621,"config":622},"Best practice videos",{"href":623,"dataGaName":624,"dataGaLocation":436},"/getting-started-videos/","best practice videos",{"text":626,"config":627},"Integrations",{"href":628,"dataGaName":629,"dataGaLocation":436},"/integrations/","integrations",{"title":631,"items":632},"Discover",[633,638,643,648,652],{"text":634,"config":635},"Customer success stories",{"href":636,"dataGaName":637,"dataGaLocation":436},"/customers/","customer success stories",{"text":639,"config":640},"Blog",{"href":641,"dataGaName":642,"dataGaLocation":436},"/blog/","blog",{"text":644,"config":645},"Demo Hub",{"href":646,"dataGaName":647,"dataGaLocation":436},"/demo-hub/","demo hub",{"text":649,"config":650},"The Source",{"href":651,"dataGaName":642,"dataGaLocation":436},"/the-source/",{"text":653,"config":654},"Remote",{"href":655,"dataGaName":656,"dataGaLocation":436},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":658,"items":659},"Connect",[660,665,670,675,680,685],{"text":661,"config":662},"GitLab Services",{"href":663,"dataGaName":664,"dataGaLocation":436},"/services/","services",{"text":666,"config":667},"Contribute",{"href":668,"dataGaName":669,"dataGaLocation":436},"https://contributors.gitlab.com","contribute",{"text":671,"config":672},"Community",{"href":673,"dataGaName":674,"dataGaLocation":436},"/community/","community",{"text":676,"config":677},"Forum",{"href":678,"dataGaName":679,"dataGaLocation":436},"https://forum.gitlab.com/","forum",{"text":681,"config":682},"Events",{"href":683,"dataGaName":684,"dataGaLocation":436},"/events/","events",{"text":686,"config":687},"Partners",{"href":688,"dataGaName":689,"dataGaLocation":436},"/partners/","partners",{"config":691,"title":694,"text":695,"link":696},{"background":692,"textColor":693},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":697,"config":698},"Read the latest",{"href":699,"dataGaName":700,"dataGaLocation":436},"/whats-new/","whats new",{"text":702,"config":703,"menu":705},"Company",{"dataNavLevelOne":704},"company",{"type":487,"columns":706},[707],{"items":708},[709,714,720,722,727,732,737,742,747,752],{"text":710,"config":711},"About",{"href":712,"dataGaName":713,"dataGaLocation":436},"/company/","about",{"text":715,"config":716,"footerGa":719},"Jobs",{"href":717,"dataGaName":718,"dataGaLocation":436},"/jobs/","jobs",{"dataGaName":718},{"text":681,"config":721},{"href":683,"dataGaName":684,"dataGaLocation":436},{"text":723,"config":724},"Leadership",{"href":725,"dataGaName":726,"dataGaLocation":436},"/company/team/e-group/","leadership",{"text":728,"config":729},"Handbook",{"href":730,"dataGaName":731,"dataGaLocation":436},"https://handbook.gitlab.com/","handbook",{"text":733,"config":734},"Investor relations",{"href":735,"dataGaName":736,"dataGaLocation":436},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":738,"config":739},"Trust Center",{"href":740,"dataGaName":741,"dataGaLocation":436},"/security/","trust center",{"text":743,"config":744},"AI Transparency Center",{"href":745,"dataGaName":746,"dataGaLocation":436},"/ai-transparency-center/","ai transparency center",{"text":748,"config":749},"Newsletter",{"href":750,"dataGaName":751,"dataGaLocation":436},"/company/contact/#contact-forms","newsletter",{"text":753,"config":754},"Press",{"href":755,"dataGaName":756,"dataGaLocation":436},"/press/","press",{"text":758,"config":759,"menu":760},"Contact us",{"dataNavLevelOne":704},{"type":487,"columns":761},[762],{"items":763},[764,769,774],{"text":765,"config":766},"Talk to sales",{"href":767,"dataGaName":768,"dataGaLocation":436},"/sales/","talk to sales",{"text":770,"config":771},"Support portal",{"href":772,"dataGaName":773,"dataGaLocation":436},"https://support.gitlab.com/hc/en-us","support portal",{"text":775,"config":776},"Customer portal",{"href":777,"dataGaName":778,"dataGaLocation":436},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":780,"login":781,"suggestions":788},"Close",{"text":782,"link":783},"To search repositories and projects, login to",{"text":784,"config":785},"gitlab.com",{"href":450,"dataGaName":786,"dataGaLocation":787},"search login","search",{"text":789,"default":790},"Suggestions",[791,793,797,799,803,807],{"text":467,"config":792},{"href":472,"dataGaName":467,"dataGaLocation":787},{"text":794,"config":795},"Code Suggestions (AI)",{"href":796,"dataGaName":794,"dataGaLocation":787},"/solutions/code-suggestions/",{"text":503,"config":798},{"href":505,"dataGaName":503,"dataGaLocation":787},{"text":800,"config":801},"GitLab on AWS",{"href":802,"dataGaName":800,"dataGaLocation":787},"/partners/technology-partners/aws/",{"text":804,"config":805},"GitLab on Google Cloud",{"href":806,"dataGaName":804,"dataGaLocation":787},"/partners/technology-partners/google-cloud-platform/",{"text":808,"config":809},"Why GitLab?",{"href":480,"dataGaName":808,"dataGaLocation":787},{"freeTrial":811,"mobileIcon":816,"desktopIcon":821,"secondaryButton":824},{"text":812,"config":813},"Start free trial",{"href":814,"dataGaName":441,"dataGaLocation":815},"https://gitlab.com/-/trials/new/","nav",{"altText":817,"config":818},"Gitlab Icon",{"src":819,"dataGaName":820,"dataGaLocation":815},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":817,"config":822},{"src":823,"dataGaName":820,"dataGaLocation":815},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":825,"config":826},"Get Started",{"href":827,"dataGaName":828,"dataGaLocation":815},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":830,"mobileIcon":834,"desktopIcon":836},{"text":831,"config":832},"Learn more about GitLab Duo",{"href":472,"dataGaName":833,"dataGaLocation":815},"gitlab duo",{"altText":817,"config":835},{"src":819,"dataGaName":820,"dataGaLocation":815},{"altText":817,"config":837},{"src":823,"dataGaName":820,"dataGaLocation":815},{"button":839,"mobileIcon":844,"desktopIcon":846},{"text":840,"config":841},"/switch",{"href":842,"dataGaName":843,"dataGaLocation":815},"#contact","switch",{"altText":817,"config":845},{"src":819,"dataGaName":820,"dataGaLocation":815},{"altText":817,"config":847},{"src":848,"dataGaName":820,"dataGaLocation":815},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":850,"mobileIcon":855,"desktopIcon":857},{"text":851,"config":852},"Back to pricing",{"href":585,"dataGaName":853,"dataGaLocation":815,"icon":854},"back to pricing","GoBack",{"altText":817,"config":856},{"src":819,"dataGaName":820,"dataGaLocation":815},{"altText":817,"config":858},{"src":823,"dataGaName":820,"dataGaLocation":815},{"title":860,"titleMobile":861,"button":862,"config":867},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":478,"config":863},{"href":864,"dataGaName":865,"dataGaLocation":866},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":868,"disabled":412},"release",{"data":870},{"text":871,"source":872,"edit":878,"contribute":883,"config":888,"items":893,"minimal":1103},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":873,"config":874},"View page source",{"href":875,"dataGaName":876,"dataGaLocation":877},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":879,"config":880},"Edit this page",{"href":881,"dataGaName":882,"dataGaLocation":877},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":884,"config":885},"Please contribute",{"href":886,"dataGaName":887,"dataGaLocation":877},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":889,"facebook":890,"youtube":891,"linkedin":892},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[894,941,995,1039,1071],{"title":583,"links":895,"subMenu":910},[896,900,905],{"text":897,"config":898},"View plans",{"href":585,"dataGaName":899,"dataGaLocation":877},"view plans",{"text":901,"config":902},"Why Premium?",{"href":903,"dataGaName":904,"dataGaLocation":877},"/pricing/premium/","why premium",{"text":906,"config":907},"Why Ultimate?",{"href":908,"dataGaName":909,"dataGaLocation":877},"/pricing/ultimate/","why ultimate",[911],{"title":912,"links":913},"Contact Us",[914,917,919,921,926,931,936],{"text":915,"config":916},"Contact sales",{"href":767,"dataGaName":446,"dataGaLocation":877},{"text":770,"config":918},{"href":772,"dataGaName":773,"dataGaLocation":877},{"text":775,"config":920},{"href":777,"dataGaName":778,"dataGaLocation":877},{"text":922,"config":923},"Status",{"href":924,"dataGaName":925,"dataGaLocation":877},"https://status.gitlab.com/","status",{"text":927,"config":928},"Terms of use",{"href":929,"dataGaName":930,"dataGaLocation":877},"/terms/","terms of use",{"text":932,"config":933},"Privacy statement",{"href":934,"dataGaName":935,"dataGaLocation":877},"/privacy/","privacy statement",{"text":937,"config":938},"Cookie preferences",{"dataGaName":939,"dataGaLocation":877,"id":940,"isOneTrustButton":415},"cookie preferences","ot-sdk-btn",{"title":483,"links":942,"subMenu":951},[943,947],{"text":944,"config":945},"DevSecOps platform",{"href":465,"dataGaName":946,"dataGaLocation":877},"devsecops platform",{"text":948,"config":949},"AI-Assisted Development",{"href":472,"dataGaName":950,"dataGaLocation":877},"ai-assisted development",[952],{"title":953,"links":954},"Topics",[955,960,965,970,975,980,985,990],{"text":956,"config":957},"CICD",{"href":958,"dataGaName":959,"dataGaLocation":877},"/topics/ci-cd/","cicd",{"text":961,"config":962},"GitOps",{"href":963,"dataGaName":964,"dataGaLocation":877},"/topics/gitops/","gitops",{"text":966,"config":967},"DevOps",{"href":968,"dataGaName":969,"dataGaLocation":877},"/topics/devops/","devops",{"text":971,"config":972},"Version Control",{"href":973,"dataGaName":974,"dataGaLocation":877},"/topics/version-control/","version control",{"text":976,"config":977},"DevSecOps",{"href":978,"dataGaName":979,"dataGaLocation":877},"/topics/devsecops/","devsecops",{"text":981,"config":982},"Cloud Native",{"href":983,"dataGaName":984,"dataGaLocation":877},"/topics/cloud-native/","cloud native",{"text":986,"config":987},"AI for Coding",{"href":988,"dataGaName":989,"dataGaLocation":877},"/topics/devops/ai-for-coding/","ai for coding",{"text":991,"config":992},"Agentic AI",{"href":993,"dataGaName":994,"dataGaLocation":877},"/topics/agentic-ai/","agentic ai",{"title":996,"links":997},"Solutions",[998,1000,1002,1007,1011,1014,1018,1021,1023,1026,1029,1034],{"text":527,"config":999},{"href":522,"dataGaName":527,"dataGaLocation":877},{"text":516,"config":1001},{"href":499,"dataGaName":500,"dataGaLocation":877},{"text":1003,"config":1004},"Agile development",{"href":1005,"dataGaName":1006,"dataGaLocation":877},"/solutions/agile-delivery/","agile delivery",{"text":1008,"config":1009},"SCM",{"href":512,"dataGaName":1010,"dataGaLocation":877},"source code management",{"text":956,"config":1012},{"href":505,"dataGaName":1013,"dataGaLocation":877},"continuous integration & delivery",{"text":1015,"config":1016},"Value stream management",{"href":555,"dataGaName":1017,"dataGaLocation":877},"value stream management",{"text":961,"config":1019},{"href":1020,"dataGaName":964,"dataGaLocation":877},"/solutions/gitops/",{"text":565,"config":1022},{"href":568,"dataGaName":569,"dataGaLocation":877},{"text":1024,"config":1025},"Small business",{"href":574,"dataGaName":575,"dataGaLocation":877},{"text":1027,"config":1028},"Public sector",{"href":580,"dataGaName":581,"dataGaLocation":877},{"text":1030,"config":1031},"Education",{"href":1032,"dataGaName":1033,"dataGaLocation":877},"/solutions/education/","education",{"text":1035,"config":1036},"Financial services",{"href":1037,"dataGaName":1038,"dataGaLocation":877},"/solutions/finance/","financial services",{"title":588,"links":1040},[1041,1043,1045,1047,1050,1052,1055,1057,1059,1061,1063,1065,1067,1069],{"text":601,"config":1042},{"href":603,"dataGaName":604,"dataGaLocation":877},{"text":606,"config":1044},{"href":608,"dataGaName":609,"dataGaLocation":877},{"text":611,"config":1046},{"href":613,"dataGaName":614,"dataGaLocation":877},{"text":616,"config":1048},{"href":618,"dataGaName":1049,"dataGaLocation":877},"docs",{"text":639,"config":1051},{"href":641,"dataGaName":642,"dataGaLocation":877},{"text":1053,"config":1054},"What's new",{"href":699,"dataGaName":700,"dataGaLocation":877},{"text":634,"config":1056},{"href":636,"dataGaName":637,"dataGaLocation":877},{"text":653,"config":1058},{"href":655,"dataGaName":656,"dataGaLocation":877},{"text":661,"config":1060},{"href":663,"dataGaName":664,"dataGaLocation":877},{"text":666,"config":1062},{"href":668,"dataGaName":669,"dataGaLocation":877},{"text":671,"config":1064},{"href":673,"dataGaName":674,"dataGaLocation":877},{"text":676,"config":1066},{"href":678,"dataGaName":679,"dataGaLocation":877},{"text":681,"config":1068},{"href":683,"dataGaName":684,"dataGaLocation":877},{"text":686,"config":1070},{"href":688,"dataGaName":689,"dataGaLocation":877},{"title":702,"links":1072},[1073,1075,1077,1079,1081,1083,1087,1092,1094,1096,1098],{"text":710,"config":1074},{"href":712,"dataGaName":704,"dataGaLocation":877},{"text":715,"config":1076},{"href":717,"dataGaName":718,"dataGaLocation":877},{"text":723,"config":1078},{"href":725,"dataGaName":726,"dataGaLocation":877},{"text":728,"config":1080},{"href":730,"dataGaName":731,"dataGaLocation":877},{"text":733,"config":1082},{"href":735,"dataGaName":736,"dataGaLocation":877},{"text":1084,"config":1085},"Sustainability",{"href":1086,"dataGaName":1084,"dataGaLocation":877},"/sustainability/",{"text":1088,"config":1089},"Diversity, inclusion and belonging (DIB)",{"href":1090,"dataGaName":1091,"dataGaLocation":877},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":738,"config":1093},{"href":740,"dataGaName":741,"dataGaLocation":877},{"text":748,"config":1095},{"href":750,"dataGaName":751,"dataGaLocation":877},{"text":753,"config":1097},{"href":755,"dataGaName":756,"dataGaLocation":877},{"text":1099,"config":1100},"Modern Slavery Transparency Statement",{"href":1101,"dataGaName":1102,"dataGaLocation":877},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1104},[1105,1108,1111],{"text":1106,"config":1107},"Terms",{"href":929,"dataGaName":930,"dataGaLocation":877},{"text":1109,"config":1110},"Cookies",{"dataGaName":939,"dataGaLocation":877,"id":940,"isOneTrustButton":415},{"text":1112,"config":1113},"Privacy",{"href":934,"dataGaName":935,"dataGaLocation":877},[1115],{"id":1116,"title":7,"body":411,"config":1117,"content":1119,"description":411,"extension":139,"meta":1123,"navigation":415,"path":1124,"seo":1125,"stem":1126,"__hash__":1127},"blogAuthors/en-us/blog/authors/miguel-rincon.yml",{"template":1118},"BlogAuthor",{"name":7,"config":1120},{"headshot":1121,"ctfId":1122},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749681865/Blog/Author%20Headshots/mrincon-headshot.jpg","mrincon",{},"/en-us/blog/authors/miguel-rincon",{},"en-us/blog/authors/miguel-rincon","UO58QQaHE3Ps_MNHXOl8JY5M_szrJJ0a_-AGWrs1aJM",[1129,1138,1146],{"title":1130,"description":1131,"heroImage":1132,"category":407,"date":1133,"authors":1134,"slug":1137,"externalUrl":411},"Confidential AI for GitLab Self-Hosted","Give developers AI coding agents in GitLab Duo without source code leaving a hardware-encrypted boundary — no GPUs needed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png","2026-08-06",[1135,1136],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1139,"description":1140,"heroImage":1141,"category":407,"date":1142,"authors":1143,"slug":1145,"externalUrl":411},"Green DevOps: Why carbon measurement belongs in your CI/CD pipeline","CI/CD pipelines have a hidden carbon cost. Here's why measuring it matters, and how you can get started with Eco CI and Carmen in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-09",[1144],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1147,"description":1148,"heroImage":1149,"category":407,"date":1150,"authors":1151,"slug":1153,"externalUrl":411},"How to build CI/CD observability at scale","This practical guide to GitLab pipeline analytics helps self-managed users gain operational insights using Prometheus and Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-04-28",[1152],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1155},[1156,1170,1182,1194],{"id":1157,"categories":1158,"header":1160,"text":1161,"button":1162,"image":1167},"ai-modernization",[1159],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1163,"config":1164},"Get your AI maturity score",{"href":1165,"dataGaName":1166,"dataGaLocation":642},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1168},{"src":1169},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1171,"categories":1172,"header":1174,"text":1161,"button":1175,"image":1179},"devops-modernization",[1173,979],"product","Are you just managing tools or shipping innovation?",{"text":1176,"config":1177},"Get your DevOps maturity score",{"href":1178,"dataGaName":1166,"dataGaLocation":642},"/assessments/devops-modernization-assessment/",{"config":1180},{"src":1181},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1183,"categories":1184,"header":1186,"text":1161,"button":1187,"image":1191},"security-modernization",[1185],"security","Are you trading speed for security?",{"text":1188,"config":1189},"Get your security maturity score",{"href":1190,"dataGaName":1166,"dataGaLocation":642},"/assessments/security-modernization-assessment/",{"config":1192},{"src":1193},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1195,"paths":1196,"header":1199,"text":1200,"button":1201,"image":1206},"github-azure-migration",[1197,1198],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":1202,"config":1203},"See how GitLab compares to GitHub",{"href":1204,"dataGaName":1205,"dataGaLocation":642},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1207},{"src":1181},{"header":1209,"blurb":1210,"button":1211,"secondaryButton":1216},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1212,"config":1213},"Get your free trial",{"href":1214,"dataGaName":441,"dataGaLocation":1215},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":915,"config":1217},{"href":767,"dataGaName":446,"dataGaLocation":1215},1786803738905]