Skip to content
Julien DanjouJulien Danjou
August 5, 2026 · 9 min read

Should you build your own merge queue?

A merge queue is a weekend prototype and a multi-year maintenance commitment. Here's how to tell which one you're actually signing up for, and the operating tail that decides it.

A basic merge queue is genuinely easy to build. Take the PRs in order, rebase each on the ones ahead of it, run CI, merge if green. You can have that working in a weekend, and with an LLM, in an afternoon.

So the honest answer to “should you build your own?” is: sometimes. Here’s how to tell.

When building your own is fine

If your repository is small, your merge volume is low, and a broken main is a minor inconvenience you can fix in minutes, build it. A serial queue that rebases and runs CI is a reasonable amount of code, and you’ll understand every line. Don’t pay a vendor for plumbing you can own outright at no real cost.

The afternoon version works right up until two things happen at once: volume climbs, and the cost of being wrong climbs with it.

The operating tail

Here’s what the prototype doesn’t include, and what you sign up to own the day you ship it.

SerialPR 1PR 2PR 3done (late)BatchedPR 1PR 2PR 3done (early)time saved
Speculative parallel testing is what makes a queue worth having at scale, and what the prototype doesn’t have.

Batching and parallelism. A serial queue tests one PR at a time, so as the team grows the queue itself becomes the bottleneck. To keep merges flowing you need to test several PRs at once, speculatively, as if the ones ahead of them will pass. That’s a different and much harder system than the serial prototype, and it’s the feature that makes a queue worth having at scale in the first place.

Bisection. The moment you batch, you inherit a new problem: when a batch goes red, which PR broke it? A naive queue throws away the whole batch and retries, punishing the innocent PRs. A good one isolates the culprit and lets the rest through. Building that well is most of the work.

Flaky tests. One flaky test will stall the entire train, repeatedly, and your queue has no idea the failure was noise. Detecting and quarantining flakes is its own project. (We wrote a lot about this.)

Priorities. Not every PR is equal. A production hotfix needs to jump the line; a release branch needs to drain before a freeze; a routine dependency bump can wait. The moment a queue exists, people want to control its order, and a priority scheme that’s predictable and still doesn’t starve the low-priority PRs is its own design problem.

The integrity invariant. The commit you tested has to be the commit you land. Same bytes. The obvious implementation reconstructs the merge commit at land time, which produces a different commit than the one CI signed off on. That drift is silent. Branch protection doesn’t catch it, because branch protection ran on the tested commit. GitHub’s own merge queue shipped exactly this bug and corrupted merges for four and a half hours. We cared enough about this class of failure to formally verify our core algorithm with TLA+.

Monitoring and capacity. Someone has to watch the queue, alert when it wedges, and keep it sized to your merge volume as the team grows. A queue nobody is watching fails silently, which for a merge queue is the worst way to fail.

Surviving GitHub itself. Your queue runs on top of GitHub’s API, and GitHub has outages, rate limits, and webhooks that arrive late or never. Each one becomes your queue’s problem to detect, back off from, and recover from without dropping a PR or merging one twice.

And the list goes on. Freezes and deployment windows. Cross-repo dependencies. CI cost, which is mostly won or lost in the queue. Reporting and audit trails. Every item is a feature your team now maintains instead of shipping your actual product.

Build is a line item. Run is a payroll line.

It’s tempting to price a merge queue as a one-time build: a few weeks of work, then it’s done. It is never done.

Building it is a line item you pay once. Running it is a payroll line you pay every month, because every item in that operating tail is somebody’s ongoing job. The prototype is the cheapest moment in the tool’s entire life. From the day it touches main, the cost is maintenance, on-call, and the new pieces you keep bolting on as your scale outgrows the version you shipped.

This is the mistake the afternoon prototype encourages. It shows you the build cost, which is now near zero, and hides the run cost, which didn’t move. You decide based on the number you can see.

Doing the ROI honestly

Put rough numbers on it, for your own team.

The serial prototype is maybe two or three weeks. A queue that survives the operating tail above is closer to a strong infrastructure engineer for a quarter to get right, then a standing slice of an engineer, call it 10 to 20 percent, forever to keep healthy, and more during the incidents. On a loaded platform-engineering salary, that recurring slice alone runs into six figures a year. Then add the opportunity cost, which is the real one: that’s your most senior infrastructure person spending their time on a problem every scaling team has already solved, instead of shipping features your customers actually asked for.

Against that, the buy side is a subscription plus an afternoon of setup, with the entire operating tail owned by someone whose only product is the queue. You also get it working today, not a quarter from now, which matters more than it looks, because teams only go looking for a merge queue once the pain is already here.

The build case wins when the tool is small and the stakes are low. It stops winning the moment the tail shows up, because the tail was the thing you were comparing against all along.

The reason that isn’t in the business case

Here’s what the ROI math misses: a lot of “build” decisions aren’t made on ROI at all.

Building your own merge queue is fun. It’s yours, you understand every line, and with an LLM you can have a working one by the afternoon and feel great about it. Those are real reasons, and none of them show up in the spreadsheet. What shows up in the spreadsheet is the justification written afterward, once the decision is already made.

There’s nothing wrong with building something because you want to. Just be honest about which one it is. If the queue is genuinely core to your business, or small enough to own outright, build it. If you’re building it because it’s more interesting than the roadmap, that’s a fine reason to spend a weekend and an expensive reason to take on a standing system that competes with your actual product for years.

The tell is what happens after the fun part ends. The prototype ships, the novelty wears off, and the operating tail is still there every month, whether or not anyone still enjoys it.

The real question

It isn’t “can we build a merge queue.” You can. It’s “do we want to own a merge queue as a standing system, forever, including the night it wedges and the day it silently lands the wrong commit.”

For a small repo, that ownership is cheap and worth it. At scale, you’re not maintaining a weekend script anymore. You’re running critical infrastructure whose failure mode is a corrupted main that nobody notices, and that work competes with the product only you can build.

That’s the line. Below it, build. Above it, the bill was always the tail, and the tail is yours the moment you ship.

That tail is the part we took off teams’ hands. We make a merge queue, so you don’t have to keep one alive.

Merge Queue

Tired of broken main branches?

Mergify's merge queue tests every PR against the latest main before merging. Try it free.

Learn about Merge Queue

Recommended posts

AI-assisted PRs break main half as often as human ones
July 27, 2026·6 min read

AI-assisted PRs break main half as often as human ones

We measured 153,000 merges across 160 engineering teams over 90 days. AI-assisted PRs broke main about half as often as non-AI ones, the broken-main rate scales 16x with team size, and private code breaks main 4.5x more than open source. Findings from the State of Merge Queues 2026 report.

Julien DanjouJulien Danjou
How we made our merge queue lower its own quality bar (only when it's drowning)
July 6, 2026·7 min read

How we made our merge queue lower its own quality bar (only when it's drowning)

Our merge queue tested every PR alone, which choked the morning a burst of agent PRs landed faster than CI could clear them. Here's the dynamic batch size that widens under load, and the production data on what it changed.

Julian MaurinJulian Maurin
Merge Queue & CI

Path Filters Are a Convenience, Not a CI Gate

June 26, 2026·8 min read

Path Filters Are a Convenience, Not a CI Gate

Skipping CI with paths: is a fine optimization until you make the check required. Then it breaks, and not because the glob is imprecise. A path-filtered workflow that doesn't run reports no status at all, so the required check sits pending and blocks the merge, or you fake it green and gate on nothing. Here's why a path filter can't be a merge gate, and what to use instead.

Julien DanjouJulien Danjou