[{"data":1,"prerenderedAt":703},["ShallowReactive",2],{"/en-us/blog/fast-search-using-postgresql-trigram/":3,"navigation-en-us":32,"banner-en-us":449,"footer-en-us":464,"Yorick Peterse":675,"next-steps-en-us":688},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":22,"_id":25,"_type":26,"title":27,"_source":28,"_file":29,"_stem":30,"_extension":31},"/en-us/blog/fast-search-using-postgresql-trigram","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Fast Search Using PostgreSQL Trigram Text Indexes","In this article we'll look at how these indexes work and how they can be used to speed up queries using LIKE conditions.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663397/Blog/Hero%20Images/logoforblogpost.jpg","https://about.gitlab.com/blog/fast-search-using-postgresql-trigram-indexes","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Fast Search Using PostgreSQL Trigram Text Indexes\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yorick Peterse\"}],\n        \"datePublished\": \"2016-03-18\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21},[18],"Yorick Peterse","2016-03-18","\nGitLab 8.6 will ship with improved search performance for PostgreSQL thanks to\nthe use of trigram indexes. In this article we'll look at how these indexes work\nand how they can be used to speed up queries using LIKE conditions.\n\n\u003C!--more-->\n\n## How to Use PostgreSQL Fast Search in GitLab?\n\nGitLab allows users to search for issues, comments, commits, code, merge\nrequests, and snippets. The traditional approach to developing a system for\nsearching data like this in an RDBMS is to simply use a LIKE condition. A LIKE\noperates on a string that specifies what to search for and optional percentage\nsigns acting as wildcards. For example, to match all values starting with\n\"Alice\" you'd use the string `'Alice%'`. If one wants to search all records in a\ntable (e.g. all users) they might write the following query:\n\n    SELECT *\n    FROM users\n    WHERE name LIKE 'Alice%';\n\nThe wildcards used for a LIKE condition can appear anywhere (and optionally\nmultiple times) in the string, as such all these values are valid:\n\n* `'Alice%'`\n* `'%Alice'`\n* `'%Alice%'`\n* `'%Al%ice%'`\n\nHowever, wildcards being allowed poses a problem: index usage. When a wildcard\nappears somewhere at the end of a string both MySQL and PostgreSQL are able to\nuse any existing indexes. However, when a wildcard appears at the start of a\nstring things become problematic. To better understand the problem, imagine you\nhave the following list of names:\n\n* Alice\n* Bob\n* Charlie\n* Eve\n* Emily\n\nWhen searching for any name containing \"li\" the only solution is to iterate over\nall values and check if each value contains the string \"li\". Because the value\ncan appear anywhere in the strings to search an index won't help as we'd still\nhave to compare every value one by one with no way of reducing the set of rows\nto search through. This in turn can lead to very slow queries depending on the\namount of data to search through.\n\n## Postgres Full Text Search\n\nSince both MySQL and PostgreSQL provide full text searching capabilities one\nsolution would be to use this instead of a regular LIKE condition. Sadly both\nimplementations are not without their problems. Up until MySQL 5.6 full text\nsearch only worked on MyISAM tables which in turn meant not being able to use\ntransactions. Both MySQL and PostgreSQL also use different syntax for searching\nand require different steps to set things up. For example, MySQL uses the\nfollowing syntax:\n\n    SELECT *\n    FROM users\n    WHERE MATCH (username) AGAINST ('yorick');\n\nPostgreSQL uses the following instead:\n\n    SELECT *\n    FROM users\n    WHERE to_tsvector('english', username) @@ to_tsquery('english', 'yorick');\n\nThe differences in syntax make the code more complex. On top of that\nPostgresSQL full text search works best when the text vectors are stored in\nphysical columns with an index. This in turn means having to adjust all your\nqueries to use these columns instead of the regular ones, resulting queries such\nas:\n\n    SELECT *\n    FROM users\n    WHERE username_tsvector @@ to_tsquery('english', 'yorick');\n\nThis assumes `username_tsvector` contains a text vector built from the data\nstored in the `username` column. To further complicate matters you'd have to set\nup a stored procedure and database trigger to keep these text vector columns in\nsync with the ones containing the raw data.\n\nAnother problem with full text search is that words are broken up according to\nthe rules defined by the language of the text. For example, on PostgreSQL\nconverting \"Yorick Peterse\" to a text vector results in the values \"peters\" and\n\"yorick\". This means that searching for \"yorick\" or \"peterse\" _will_ match the\ndata, but searching for \"yor\" _will not_. To showcase this we can run the\nfollowing query in PostgreSQL:\n\n    SELECT 1\n    WHERE to_tsvector('english', 'Yorick Peterse') @@ to_tsquery('english', 'peterse');\n\nHere `to_tsvector()` creates a text vector with English as the language and\n\"Yorick Peterse\" as the input. The `to_tsquery()` function in turn creates a\ntext search query with English as the language and \"peterse\" as the input.\n\nRunning this query will result in a single row being returned. On the other\nhand, this will return no rows:\n\n    SELECT 1\n    WHERE to_tsvector('english', 'Yorick Peterse') @@ to_tsquery('english', 'yor');\n\nThis is problematic when you don't know exactly what you're looking for, for\nexample when you're looking for a person but only know part of their first name.\n\nIn short, full text search is only really an option if you only support\nPostgreSQL or MySQL as supporting both leads to a lot of unwanted complexity.\n\n## Trigram Indexes\n\nWhile MySQL offers no further solutions (that I know of), PostgreSQL on the\nother hand has some extra tricks up its sleeves: trigram indexes. Trigram\nindexes work by breaking up text in [trigrams][trigrams]. Trigrams are basically\nwords broken up into sequences of 3 letters. For example, the trigram for\n\"alice\" would be:\n\n    {ali, lic, ice}\n\nPostgreSQL supports trigram indexes and operations via the [pg_trgm][pg_trgm]\nextension. This extension adds a few functions, operators, and support for\ntrigram indexes (Postgres using GIN or GiST indexes to be exact). To see what kind of\ntrigrams PostgreSQL can produce we can run the following query:\n\n    select show_trgm('alice');\n\nThis will generate the trigrams for the string \"alice\", producing the following\noutput:\n\n                show_trgm\n    ---------------------------------\n     {\"  a\",\" al\",ali,\"ce \",ice,lic}\n\nA big benefit of this extension is that these trigram indexes can be used by the\nLIKE and ILIKE conditions without having to change your queries or setting up\ncomplex full text search systems. There are 2 requirements for this to work:\n\n1. The index created must be either a GIN or a GiST index, in case of GitLab we\n   went with Postgres using GIN indexes due to them leading to better query timings (at the\n   cost of being larger and somewhat slower to build).\n2. The index must have the appropriate [operator class][opclass] set.\n\nIn case of a GIN index the operator class we have to use is called\n`gin_trgm_ops`. We can create the appropriate indexes using a query such as the\nfollowing:\n\n    CREATE INDEX CONCURRENTLY index_issues_on_title_trigram\n    ON issues\n    USING gin (title gin_trgm_ops);\n\nTo showcase the impact these indexes have on performance let's use the following\nquery as an example:\n\n    SELECT COUNT(*)\n    FROM users\n    WHERE username ILIKE '%yorick%';\n\nThis query counts the amount of users where the username contains the string\n\"yorick\", regardless of the casing. Running this query on my local PostgreSQL\ndatabase takes around 160 milliseconds and produces the following query plan:\n\n     Aggregate  (cost=8143.40..8143.41 rows=1 width=0) (actual time=157.981..157.982 rows=1 loops=1)\n       ->  Index Only Scan using index_users_on_username on users  (cost=0.42..8143.34 rows=26 width=0) (actual time=155.153..157.974 rows=6 loops=1)\n             Filter: (username ~~* '%yorick%'::text)\n             Rows Removed by Filter: 257532\n             Heap Fetches: 0\n     Planning time: 0.143 ms\n     Execution time: 158.008 ms\n\nTo speed this up we'll run the following to create an index:\n\n    CREATE INDEX CONCURRENTLY index_users_on_username_trigram\n    ON users\n    USING gin (username gin_trgm_ops);\n\nIf we now re-run the query it takes only around 0.2 milliseconds and produces\nthe following query plan:\n\n     Aggregate  (cost=152.41..152.42 rows=1 width=0) (actual time=0.128..0.128 rows=1 loops=1)\n       ->  Bitmap Heap Scan on users  (cost=52.20..152.35 rows=26 width=0) (actual time=0.115..0.126 rows=6 loops=1)\n             Recheck Cond: (username ~~* '%yorick%'::text)\n             Heap Blocks: exact=6\n             ->  Bitmap Index Scan on index_users_on_username_trigram  (cost=0.00..52.19 rows=26 width=0) (actual time=0.106..0.106 rows=6 loops=1)\n                   Index Cond: (username ~~* '%yorick%'::text)\n     Planning time: 0.366 ms\n     Execution time: 0.167 ms\n\nIn other words, creating the trigram index results in the query being around\n946 times faster.\n\n## GitLab & Trigram Indexes\n\nGitLab 8.6 will create trigram indexes for PostgreSQL users leading to vastly\nimproved search performance (though there's still some work to be done in the\nfuture). To make this work (while still supporting MySQL) we did have to port\nover some changes from an open Rails pull request to ensure the indexes were\ndumped properly to `db/schema.rb`. These changes can be found in\n[config/initializers/postgresql_opclasses_support.rb][opclass-support] and were\ntaken from [Rails pull request #19090][rails-pr-19090].\n\nWe also had to make some changes to ensure MySQL doesn't end up trying to create\nthese indexes when loading the schema definition into a database. For example,\n`db/schema.rb` contains lines such as `add_index ..., using: :gin` and the\n`using` option is passed straight to the underlying database. Since MySQL\ndoesn't support GIN indexes this would lead to database errors when trying to\nload `db/schema.rb`. The code that makes this work can be found in\n[config/initializers/mysql_ignore_postgresql_options.rb][mysql-ignore-pg].\n\nFinally we made some small changes to the code to ensure queries automatically\nuse ILIKE on PostgreSQL instead of `lower(some_column)` as ILIKE performs quite\na bit better. On MySQL a regular LIKE is used as it's already case-insensitive.\n\nAll of the other details can be found in GitLab CE merge request [\"Refactor\nsearching and use PostgreSQL trigram indexes for significantly improved\nperformance\"][mr2987].\n\n[trigrams]: https://en.wikipedia.org/wiki/Trigram\n[pg_trgm]: http://www.postgresql.org/docs/current/static/pgtrgm.html\n[opclass]: http://www.postgresql.org/docs/current/static/indexes-opclass.html\n[mr2987]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2987\n[opclass-support]: https://gitlab.com/gitlab-org/gitlab-ce/blob/0602091f0cdebbc3183732dee78c38f89b4b7d01/config/initializers/postgresql_opclasses_support.rb\n[mysql-ignore-pg]: https://gitlab.com/gitlab-org/gitlab-ce/blob/0602091f0cdebbc3183732dee78c38f89b4b7d01/config/initializers/mysql_ignore_postgresql_options.rb\n[rails-pr-19090]: https://github.com/rails/rails/pull/19090\n","engineering",{"slug":23,"featured":6,"template":24},"fast-search-using-postgresql-trigram","BlogPost","content:en-us:blog:fast-search-using-postgresql-trigram.yml","yaml","Fast Search Using Postgresql Trigram","content","en-us/blog/fast-search-using-postgresql-trigram.yml","en-us/blog/fast-search-using-postgresql-trigram","yml",{"_path":33,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":35,"_id":445,"_type":26,"title":446,"_source":28,"_file":447,"_stem":448,"_extension":31},"/shared/en-us/main-navigation","en-us",{"logo":36,"freeTrial":41,"sales":46,"login":51,"items":56,"search":386,"minimal":417,"duo":436},{"config":37},{"href":38,"dataGaName":39,"dataGaLocation":40},"/","gitlab logo","header",{"text":42,"config":43},"Get free trial",{"href":44,"dataGaName":45,"dataGaLocation":40},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":47,"config":48},"Talk to sales",{"href":49,"dataGaName":50,"dataGaLocation":40},"/sales/","sales",{"text":52,"config":53},"Sign in",{"href":54,"dataGaName":55,"dataGaLocation":40},"https://gitlab.com/users/sign_in/","sign in",[57,101,197,202,307,367],{"text":58,"config":59,"cards":61,"footer":84},"Platform",{"dataNavLevelOne":60},"platform",[62,68,76],{"title":58,"description":63,"link":64},"The most comprehensive AI-powered DevSecOps Platform",{"text":65,"config":66},"Explore our Platform",{"href":67,"dataGaName":60,"dataGaLocation":40},"/platform/",{"title":69,"description":70,"link":71},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":72,"config":73},"Meet GitLab Duo",{"href":74,"dataGaName":75,"dataGaLocation":40},"/gitlab-duo/","gitlab duo ai",{"title":77,"description":78,"link":79},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":80,"config":81},"Learn more",{"href":82,"dataGaName":83,"dataGaLocation":40},"/why-gitlab/","why gitlab",{"title":85,"items":86},"Get started with",[87,92,97],{"text":88,"config":89},"Platform Engineering",{"href":90,"dataGaName":91,"dataGaLocation":40},"/solutions/platform-engineering/","platform engineering",{"text":93,"config":94},"Developer Experience",{"href":95,"dataGaName":96,"dataGaLocation":40},"/developer-experience/","Developer experience",{"text":98,"config":99},"MLOps",{"href":100,"dataGaName":98,"dataGaLocation":40},"/topics/devops/the-role-of-ai-in-devops/",{"text":102,"left":103,"config":104,"link":106,"lists":110,"footer":179},"Product",true,{"dataNavLevelOne":105},"solutions",{"text":107,"config":108},"View all Solutions",{"href":109,"dataGaName":105,"dataGaLocation":40},"/solutions/",[111,136,158],{"title":112,"description":113,"link":114,"items":119},"Automation","CI/CD and automation to accelerate deployment",{"config":115},{"icon":116,"href":117,"dataGaName":118,"dataGaLocation":40},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[120,124,128,132],{"text":121,"config":122},"CI/CD",{"href":123,"dataGaLocation":40,"dataGaName":121},"/solutions/continuous-integration/",{"text":125,"config":126},"AI-Assisted Development",{"href":74,"dataGaLocation":40,"dataGaName":127},"AI assisted development",{"text":129,"config":130},"Source Code Management",{"href":131,"dataGaLocation":40,"dataGaName":129},"/solutions/source-code-management/",{"text":133,"config":134},"Automated Software Delivery",{"href":117,"dataGaLocation":40,"dataGaName":135},"Automated software delivery",{"title":137,"description":138,"link":139,"items":144},"Security","Deliver code faster without compromising security",{"config":140},{"href":141,"dataGaName":142,"dataGaLocation":40,"icon":143},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[145,148,153],{"text":146,"config":147},"Security & Compliance",{"href":141,"dataGaLocation":40,"dataGaName":146},{"text":149,"config":150},"Software Supply Chain Security",{"href":151,"dataGaLocation":40,"dataGaName":152},"/solutions/supply-chain/","Software supply chain security",{"text":154,"config":155},"Compliance & Governance",{"href":156,"dataGaLocation":40,"dataGaName":157},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":159,"link":160,"items":165},"Measurement",{"config":161},{"icon":162,"href":163,"dataGaName":164,"dataGaLocation":40},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[166,170,174],{"text":167,"config":168},"Visibility & Measurement",{"href":163,"dataGaLocation":40,"dataGaName":169},"Visibility and Measurement",{"text":171,"config":172},"Value Stream Management",{"href":173,"dataGaLocation":40,"dataGaName":171},"/solutions/value-stream-management/",{"text":175,"config":176},"Analytics & Insights",{"href":177,"dataGaLocation":40,"dataGaName":178},"/solutions/analytics-and-insights/","Analytics and insights",{"title":180,"items":181},"GitLab for",[182,187,192],{"text":183,"config":184},"Enterprise",{"href":185,"dataGaLocation":40,"dataGaName":186},"/enterprise/","enterprise",{"text":188,"config":189},"Small Business",{"href":190,"dataGaLocation":40,"dataGaName":191},"/small-business/","small business",{"text":193,"config":194},"Public Sector",{"href":195,"dataGaLocation":40,"dataGaName":196},"/solutions/public-sector/","public sector",{"text":198,"config":199},"Pricing",{"href":200,"dataGaName":201,"dataGaLocation":40,"dataNavLevelOne":201},"/pricing/","pricing",{"text":203,"config":204,"link":206,"lists":210,"feature":294},"Resources",{"dataNavLevelOne":205},"resources",{"text":207,"config":208},"View all resources",{"href":209,"dataGaName":205,"dataGaLocation":40},"/resources/",[211,244,266],{"title":212,"items":213},"Getting started",[214,219,224,229,234,239],{"text":215,"config":216},"Install",{"href":217,"dataGaName":218,"dataGaLocation":40},"/install/","install",{"text":220,"config":221},"Quick start guides",{"href":222,"dataGaName":223,"dataGaLocation":40},"/get-started/","quick setup checklists",{"text":225,"config":226},"Learn",{"href":227,"dataGaLocation":40,"dataGaName":228},"https://university.gitlab.com/","learn",{"text":230,"config":231},"Product documentation",{"href":232,"dataGaName":233,"dataGaLocation":40},"https://docs.gitlab.com/","product documentation",{"text":235,"config":236},"Best practice videos",{"href":237,"dataGaName":238,"dataGaLocation":40},"/getting-started-videos/","best practice videos",{"text":240,"config":241},"Integrations",{"href":242,"dataGaName":243,"dataGaLocation":40},"/integrations/","integrations",{"title":245,"items":246},"Discover",[247,252,256,261],{"text":248,"config":249},"Customer success stories",{"href":250,"dataGaName":251,"dataGaLocation":40},"/customers/","customer success stories",{"text":253,"config":254},"Blog",{"href":255,"dataGaName":5,"dataGaLocation":40},"/blog/",{"text":257,"config":258},"Remote",{"href":259,"dataGaName":260,"dataGaLocation":40},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":262,"config":263},"TeamOps",{"href":264,"dataGaName":265,"dataGaLocation":40},"/teamops/","teamops",{"title":267,"items":268},"Connect",[269,274,279,284,289],{"text":270,"config":271},"GitLab Services",{"href":272,"dataGaName":273,"dataGaLocation":40},"/services/","services",{"text":275,"config":276},"Community",{"href":277,"dataGaName":278,"dataGaLocation":40},"/community/","community",{"text":280,"config":281},"Forum",{"href":282,"dataGaName":283,"dataGaLocation":40},"https://forum.gitlab.com/","forum",{"text":285,"config":286},"Events",{"href":287,"dataGaName":288,"dataGaLocation":40},"/events/","events",{"text":290,"config":291},"Partners",{"href":292,"dataGaName":293,"dataGaLocation":40},"/partners/","partners",{"backgroundColor":295,"textColor":296,"text":297,"image":298,"link":302},"#2f2a6b","#fff","Insights for the future of software development",{"altText":299,"config":300},"the source promo card",{"src":301},"/images/navigation/the-source-promo-card.svg",{"text":303,"config":304},"Read the latest",{"href":305,"dataGaName":306,"dataGaLocation":40},"/the-source/","the source",{"text":308,"config":309,"lists":311},"Company",{"dataNavLevelOne":310},"company",[312],{"items":313},[314,319,325,327,332,337,342,347,352,357,362],{"text":315,"config":316},"About",{"href":317,"dataGaName":318,"dataGaLocation":40},"/company/","about",{"text":320,"config":321,"footerGa":324},"Jobs",{"href":322,"dataGaName":323,"dataGaLocation":40},"/jobs/","jobs",{"dataGaName":323},{"text":285,"config":326},{"href":287,"dataGaName":288,"dataGaLocation":40},{"text":328,"config":329},"Leadership",{"href":330,"dataGaName":331,"dataGaLocation":40},"/company/team/e-group/","leadership",{"text":333,"config":334},"Team",{"href":335,"dataGaName":336,"dataGaLocation":40},"/company/team/","team",{"text":338,"config":339},"Handbook",{"href":340,"dataGaName":341,"dataGaLocation":40},"https://handbook.gitlab.com/","handbook",{"text":343,"config":344},"Investor relations",{"href":345,"dataGaName":346,"dataGaLocation":40},"https://ir.gitlab.com/","investor relations",{"text":348,"config":349},"Trust Center",{"href":350,"dataGaName":351,"dataGaLocation":40},"/security/","trust center",{"text":353,"config":354},"AI Transparency Center",{"href":355,"dataGaName":356,"dataGaLocation":40},"/ai-transparency-center/","ai transparency center",{"text":358,"config":359},"Newsletter",{"href":360,"dataGaName":361,"dataGaLocation":40},"/company/contact/","newsletter",{"text":363,"config":364},"Press",{"href":365,"dataGaName":366,"dataGaLocation":40},"/press/","press",{"text":368,"config":369,"lists":370},"Contact us",{"dataNavLevelOne":310},[371],{"items":372},[373,376,381],{"text":47,"config":374},{"href":49,"dataGaName":375,"dataGaLocation":40},"talk to sales",{"text":377,"config":378},"Get help",{"href":379,"dataGaName":380,"dataGaLocation":40},"/support/","get help",{"text":382,"config":383},"Customer portal",{"href":384,"dataGaName":385,"dataGaLocation":40},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":387,"login":388,"suggestions":395},"Close",{"text":389,"link":390},"To search repositories and projects, login to",{"text":391,"config":392},"gitlab.com",{"href":54,"dataGaName":393,"dataGaLocation":394},"search login","search",{"text":396,"default":397},"Suggestions",[398,400,404,406,410,414],{"text":69,"config":399},{"href":74,"dataGaName":69,"dataGaLocation":394},{"text":401,"config":402},"Code Suggestions (AI)",{"href":403,"dataGaName":401,"dataGaLocation":394},"/solutions/code-suggestions/",{"text":121,"config":405},{"href":123,"dataGaName":121,"dataGaLocation":394},{"text":407,"config":408},"GitLab on AWS",{"href":409,"dataGaName":407,"dataGaLocation":394},"/partners/technology-partners/aws/",{"text":411,"config":412},"GitLab on Google Cloud",{"href":413,"dataGaName":411,"dataGaLocation":394},"/partners/technology-partners/google-cloud-platform/",{"text":415,"config":416},"Why GitLab?",{"href":82,"dataGaName":415,"dataGaLocation":394},{"freeTrial":418,"mobileIcon":423,"desktopIcon":428,"secondaryButton":431},{"text":419,"config":420},"Start free trial",{"href":421,"dataGaName":45,"dataGaLocation":422},"https://gitlab.com/-/trials/new/","nav",{"altText":424,"config":425},"Gitlab Icon",{"src":426,"dataGaName":427,"dataGaLocation":422},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":424,"config":429},{"src":430,"dataGaName":427,"dataGaLocation":422},"/images/brand/gitlab-logo-type.svg",{"text":432,"config":433},"Get Started",{"href":434,"dataGaName":435,"dataGaLocation":422},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":437,"mobileIcon":441,"desktopIcon":443},{"text":438,"config":439},"Learn more about GitLab Duo",{"href":74,"dataGaName":440,"dataGaLocation":422},"gitlab duo",{"altText":424,"config":442},{"src":426,"dataGaName":427,"dataGaLocation":422},{"altText":424,"config":444},{"src":430,"dataGaName":427,"dataGaLocation":422},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":450,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"title":451,"button":452,"image":456,"config":459,"_id":461,"_type":26,"_source":28,"_file":462,"_stem":463,"_extension":31},"/shared/en-us/banner","is now in public beta!",{"text":80,"config":453},{"href":454,"dataGaName":455,"dataGaLocation":40},"/gitlab-duo/agent-platform/","duo banner",{"config":457},{"src":458},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":460},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":465,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":466,"_id":671,"_type":26,"title":672,"_source":28,"_file":673,"_stem":674,"_extension":31},"/shared/en-us/main-footer",{"text":467,"source":468,"edit":474,"contribute":479,"config":484,"items":489,"minimal":663},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":469,"config":470},"View page source",{"href":471,"dataGaName":472,"dataGaLocation":473},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":475,"config":476},"Edit this page",{"href":477,"dataGaName":478,"dataGaLocation":473},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":480,"config":481},"Please contribute",{"href":482,"dataGaName":483,"dataGaLocation":473},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":485,"facebook":486,"youtube":487,"linkedin":488},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[490,513,570,599,633],{"title":58,"links":491,"subMenu":496},[492],{"text":493,"config":494},"DevSecOps platform",{"href":67,"dataGaName":495,"dataGaLocation":473},"devsecops platform",[497],{"title":198,"links":498},[499,503,508],{"text":500,"config":501},"View plans",{"href":200,"dataGaName":502,"dataGaLocation":473},"view plans",{"text":504,"config":505},"Why Premium?",{"href":506,"dataGaName":507,"dataGaLocation":473},"/pricing/premium/","why premium",{"text":509,"config":510},"Why Ultimate?",{"href":511,"dataGaName":512,"dataGaLocation":473},"/pricing/ultimate/","why ultimate",{"title":514,"links":515},"Solutions",[516,521,524,526,531,536,540,543,547,552,554,557,560,565],{"text":517,"config":518},"Digital transformation",{"href":519,"dataGaName":520,"dataGaLocation":473},"/topics/digital-transformation/","digital transformation",{"text":146,"config":522},{"href":141,"dataGaName":523,"dataGaLocation":473},"security & compliance",{"text":135,"config":525},{"href":117,"dataGaName":118,"dataGaLocation":473},{"text":527,"config":528},"Agile development",{"href":529,"dataGaName":530,"dataGaLocation":473},"/solutions/agile-delivery/","agile delivery",{"text":532,"config":533},"Cloud transformation",{"href":534,"dataGaName":535,"dataGaLocation":473},"/topics/cloud-native/","cloud transformation",{"text":537,"config":538},"SCM",{"href":131,"dataGaName":539,"dataGaLocation":473},"source code management",{"text":121,"config":541},{"href":123,"dataGaName":542,"dataGaLocation":473},"continuous integration & delivery",{"text":544,"config":545},"Value stream management",{"href":173,"dataGaName":546,"dataGaLocation":473},"value stream management",{"text":548,"config":549},"GitOps",{"href":550,"dataGaName":551,"dataGaLocation":473},"/solutions/gitops/","gitops",{"text":183,"config":553},{"href":185,"dataGaName":186,"dataGaLocation":473},{"text":555,"config":556},"Small business",{"href":190,"dataGaName":191,"dataGaLocation":473},{"text":558,"config":559},"Public sector",{"href":195,"dataGaName":196,"dataGaLocation":473},{"text":561,"config":562},"Education",{"href":563,"dataGaName":564,"dataGaLocation":473},"/solutions/education/","education",{"text":566,"config":567},"Financial services",{"href":568,"dataGaName":569,"dataGaLocation":473},"/solutions/finance/","financial services",{"title":203,"links":571},[572,574,576,578,581,583,585,587,589,591,593,595,597],{"text":215,"config":573},{"href":217,"dataGaName":218,"dataGaLocation":473},{"text":220,"config":575},{"href":222,"dataGaName":223,"dataGaLocation":473},{"text":225,"config":577},{"href":227,"dataGaName":228,"dataGaLocation":473},{"text":230,"config":579},{"href":232,"dataGaName":580,"dataGaLocation":473},"docs",{"text":253,"config":582},{"href":255,"dataGaName":5,"dataGaLocation":473},{"text":248,"config":584},{"href":250,"dataGaName":251,"dataGaLocation":473},{"text":257,"config":586},{"href":259,"dataGaName":260,"dataGaLocation":473},{"text":270,"config":588},{"href":272,"dataGaName":273,"dataGaLocation":473},{"text":262,"config":590},{"href":264,"dataGaName":265,"dataGaLocation":473},{"text":275,"config":592},{"href":277,"dataGaName":278,"dataGaLocation":473},{"text":280,"config":594},{"href":282,"dataGaName":283,"dataGaLocation":473},{"text":285,"config":596},{"href":287,"dataGaName":288,"dataGaLocation":473},{"text":290,"config":598},{"href":292,"dataGaName":293,"dataGaLocation":473},{"title":308,"links":600},[601,603,605,607,609,611,613,617,622,624,626,628],{"text":315,"config":602},{"href":317,"dataGaName":310,"dataGaLocation":473},{"text":320,"config":604},{"href":322,"dataGaName":323,"dataGaLocation":473},{"text":328,"config":606},{"href":330,"dataGaName":331,"dataGaLocation":473},{"text":333,"config":608},{"href":335,"dataGaName":336,"dataGaLocation":473},{"text":338,"config":610},{"href":340,"dataGaName":341,"dataGaLocation":473},{"text":343,"config":612},{"href":345,"dataGaName":346,"dataGaLocation":473},{"text":614,"config":615},"Sustainability",{"href":616,"dataGaName":614,"dataGaLocation":473},"/sustainability/",{"text":618,"config":619},"Diversity, inclusion and belonging (DIB)",{"href":620,"dataGaName":621,"dataGaLocation":473},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":348,"config":623},{"href":350,"dataGaName":351,"dataGaLocation":473},{"text":358,"config":625},{"href":360,"dataGaName":361,"dataGaLocation":473},{"text":363,"config":627},{"href":365,"dataGaName":366,"dataGaLocation":473},{"text":629,"config":630},"Modern Slavery Transparency Statement",{"href":631,"dataGaName":632,"dataGaLocation":473},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":634,"links":635},"Contact Us",[636,639,641,643,648,653,658],{"text":637,"config":638},"Contact an expert",{"href":49,"dataGaName":50,"dataGaLocation":473},{"text":377,"config":640},{"href":379,"dataGaName":380,"dataGaLocation":473},{"text":382,"config":642},{"href":384,"dataGaName":385,"dataGaLocation":473},{"text":644,"config":645},"Status",{"href":646,"dataGaName":647,"dataGaLocation":473},"https://status.gitlab.com/","status",{"text":649,"config":650},"Terms of use",{"href":651,"dataGaName":652,"dataGaLocation":473},"/terms/","terms of use",{"text":654,"config":655},"Privacy statement",{"href":656,"dataGaName":657,"dataGaLocation":473},"/privacy/","privacy statement",{"text":659,"config":660},"Cookie preferences",{"dataGaName":661,"dataGaLocation":473,"id":662,"isOneTrustButton":103},"cookie preferences","ot-sdk-btn",{"items":664},[665,667,669],{"text":649,"config":666},{"href":651,"dataGaName":652,"dataGaLocation":473},{"text":654,"config":668},{"href":656,"dataGaName":657,"dataGaLocation":473},{"text":659,"config":670},{"dataGaName":661,"dataGaLocation":473,"id":662,"isOneTrustButton":103},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[676],{"_path":677,"_dir":678,"_draft":6,"_partial":6,"_locale":7,"content":679,"config":683,"_id":685,"_type":26,"title":18,"_source":28,"_file":686,"_stem":687,"_extension":31},"/en-us/blog/authors/yorick-peterse","authors",{"name":18,"config":680},{"headshot":681,"ctfId":682},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","Yorick-Peterse",{"template":684},"BlogAuthor","content:en-us:blog:authors:yorick-peterse.yml","en-us/blog/authors/yorick-peterse.yml","en-us/blog/authors/yorick-peterse",{"_path":689,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"header":690,"eyebrow":691,"blurb":692,"button":693,"secondaryButton":697,"_id":699,"_type":26,"title":700,"_source":28,"_file":701,"_stem":702,"_extension":31},"/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":42,"config":694},{"href":695,"dataGaName":45,"dataGaLocation":696},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":47,"config":698},{"href":49,"dataGaName":50,"dataGaLocation":696},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1753981624511]