GitLab hands rate limiting migration to AI agents: 14 specs and 30+ merge requests
A GitLab team of three engineers and a set of AI agents ran an experiment: could agents migrate part of a legacy rate limiting system without lowering the reliability bar? The answer was yes. The agents wrote specifications, implemented changes and prepared merge requests through GitLab Duo Agent Platform, while humans handled architecture and final review. The result: 14 numbered specifications and more than 30 merge requests to the labkit-ruby library.
AI-processed from GitLab Blog; edited by Hamidun News
A small GitLab team ran an experiment and used AI agents to migrate part of a legacy rate limiting system to a single implementation in the labkit-ruby library, without lowering the reliability bar. The team itself calls the outcome a success.
What the system looked like before the migration
For years, GitLab ran two rate limiting paths in parallel: the application-level `Gitlab::ApplicationRateLimiter` with 121 keys, and a separate Rack-level system. The goal of the migration was to merge both paths into a single implementation in `labkit-ruby`, so the system would be observable, testable and behave the same way across all parts of the product. Every request to the GitLab monolith passes through this system, so its failures must be visible and reversible.
Who worked on the migration, and how
Three GitLab engineers and a set of AI agents worked on the project.
- Max Woolf, Staff Backend Engineer on the API Platform team, handled the monolith side and shipped most of the releases
- Bob Van Landuyt of the Scalability team handled the library itself and the solution's architecture
- Several other engineers joined on an ad hoc basis to get up to speed on the context and help with code and review
- The team used GitLab Duo Agent Platform and GitLab Duo Code Review
The agents read context, drafted specifications, implemented changes limited in scope, wrote tests and did a preliminary review of merge requests. Humans kept scope, architecture, releases and the final decision.
How the workflow was set up
The team followed a strict loop: read the epic, write a spec, run an adversarial review of it, start implementation only once blockers were cleared, verify the result with explicit evidence, run an adversarial review of the merge request itself, escalate to human review, and only then merge. Adversarial review was capped at two rounds, after which the decision had to go to a human.
- The team shipped 14 numbered specifications for the project
- More than 30 merge requests landed in the `labkit-ruby` library
- In practice, how strictly the loop was applied varied from engineer to engineer: Bob Van Landuyt often ran several rounds of spec and review on his own before showing a shared artifact to the team
What it means
GitLab's experiment shows that AI agents can already take on the routine part of migrating legacy code (draft specs, implementation and tests), but it is the strict workflow, the team structure and mandatory human review that determine whether the system stays as reliable as before. The authors say outright that the agents work, but they also expose weak spots in how a team usually organizes its work. The review loop and observability turned out to be just as important as the agents' capabilities.
FAQ
How many people worked on the rate limiting migration at
GitLab?
Three GitLab engineers worked on the project, Max Woolf, Bob Van Landuyt and several others who joined on an ad hoc basis, together with a set of AI agents built on GitLab Duo Agent Platform.
How much code and how many specifications did the team ship?
During the experiment, the team prepared 14 numbered specifications and submitted more than 30 merge requests to the labkit-ruby library.
Key Questions Answered
How many people worked on the rate limiting migration at GitLab?
Three GitLab engineers worked on the project, Max Woolf, Bob Van Landuyt and several others who joined on an ad hoc basis, together with a set of AI agents built on GitLab Duo Agent Platform.
How much code and how many specifications did the team ship?
During the experiment, the team prepared 14 numbered specifications and submitted more than 30 merge requests to the labkit-ruby library.
What the system looked like before the migration?
For years, GitLab ran two rate limiting paths in parallel: the application-level `Gitlab::ApplicationRateLimiter` with 121 keys, and a separate Rack-level system. The goal of the migration was to merge both paths into a single implementation in `labkit-ruby`, so the system would be observable, testable and behave the same way across all parts of the product. Every request to the GitLab monolith passes through this system, so its failures must be visible and reversible.
Test Frontier LLMs & Autonomous Agents in One Workspace
Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.
The AI world, distilled — once a week
Seven stories that actually mattered, hand-picked. No noise, no reposts, no press releases.
Done! Check your inbox for a confirmation.