Skip to content
.md

What Happens Without a Merge Queue

When main breaks, failures cascade. This page shows what happens and why the costs exceed what most teams expect.

Two developers, Alice and Bob, work on separate features.

CI SystemMain BranchBobAliceCI SystemMain BranchBobAliceMain is at commit M1 ✅Main is now at M2Main is now at M3🔥 Main is brokenStart feature branch (from M1)Start feature branch (from M1)Open PR, run CI✅ Tests passOpen PR, run CI✅ Tests passMerge PRMerge PRPost-merge CI❌ Tests fail!

Both PRs were tested against M1 and passed. But Alice’s changes (M2) and Bob’s changes (M3) conflict in ways that neither CI run could detect. Now main is broken.

Your codebase has a utility module:

utils.py
def calculate_tax(amount):
return amount * 0.2

Alice is refactoring. She renames utils.py to helpers.py and updates all existing imports:

# helpers.py (renamed from utils.py)
def calculate_tax(amount):
return amount * 0.2

Bob is building a new feature. He adds code that imports from utils:

# checkout.py (new file)
from utils import calculate_tax
def process_order(total):
tax = calculate_tax(total)
return total + tax

Both PRs pass CI:

  • Alice’s PR: All tests pass—she updated every import
  • Bob’s PR: All tests pass—utils.py still exists on his branch

There’s no merge conflict—they touched different files. Git happily merges both.

But now checkout.py imports from utils, which no longer exists. Main is broken.

ModuleNotFoundError: No module named 'utils'

This pattern repeats with renamed functions, deleted code, changed signatures, and modified configuration. No merge conflict to warn you—just broken code on main.

Someone notices main is broken. Maybe it’s the post-merge CI. Maybe it’s a developer who just pulled latest. Maybe it’s a failed deployment.

🔥 Main is broken

Who broke it?

Git blame / bisect

Was it Alice's PR?

Was it Bob's PR?

Is it the interaction?

Alice investigates

Bob investigates

Both investigate

Time lost: 15 minutes to several hours, depending on how obvious the failure is.

While main is broken:

Team Impact

Dev 1: PR ready to merge

❌ Blocked

Dev 2: PR ready to merge

❌ Blocked

Dev 3: Starting new work

⚠️ Based on broken code

Dev 4: Needs to deploy

❌ Blocked

  • Developers with ready PRs can’t merge—the policy is “don’t merge to a broken main”
  • Developers starting new work base their branches on broken code
  • Deployments are blocked until main is fixed
  • Hotfixes become complex because you can’t deploy the fix without also deploying the broken code

Cost: If you have 10 developers and main is broken for 2 hours, that’s 20 developer-hours of disruption.

Someone identifies the problem and creates a fix PR.

Main BranchCI SystemFix PRDeveloperMain BranchCI SystemFix PRDeveloperCI runs against broken mainHard to know if fix workswhen base is brokenCreate fix PRRun CITests... pass? fail?

Problem: It’s hard to verify the fix works because CI is running against broken main. You might:

  • Think you fixed it, but you didn’t
  • Fix one issue but introduce another
  • Have to iterate multiple times

Time lost: 30 minutes to several hours for the fix itself.

The fix lands. Main is green again. But now:

Yes

No

Fix merged, main is green

Every in-flight PR is stale

PR 1: Must rebase

PR 2: Must rebase

PR 3: Must rebase

PR 4: Must rebase

Re-run CI

All pass?

Start merging again

More conflicts discovered

🔥 Cycle repeats?

Every developer with an in-flight PR must:

  1. Rebase onto the fixed main
  2. Resolve any conflicts with the fix
  3. Re-run CI
  4. Wait in line to merge again

Cost: If 8 PRs were in flight, and each rebase + CI takes 30 minutes, that’s 4 hours of additional wait time across the team.

The worst part: the same conditions that caused the break still exist.

No

Yes

8 PRs ready to merge

All based on new main

First PR merges

Second PR merges

Do they conflict?

Keep merging...

🔥 Main breaks again

Without a merge queue, you’re right back where you started. The PRs were rebased, but they were only tested individually, not against each other. The cycle can repeat.

Every time a developer is blocked, they have to:

  1. Stop what they’re doing
  2. Investigate or wait
  3. Resume their original work (losing context)

Studies show it takes 23 minutes to regain focus after an interruption. A broken main interrupts everyone.

If main breaks once per week and takes 2 hours to fix, the direct cost is 2 hours. But the indirect cost is:

  • 2 hours × N developers blocked
  • Time to rebase all in-flight PRs
  • CI resources wasted on broken runs
  • Deployment delays
  • Possible customer impact if caught in a release cycle

Teams that experience frequent broken mains develop defensive behaviors:

  • Hesitation to merge (“let someone else go first”)
  • Over-reliance on manual testing
  • Slower release cycles
  • Reduced confidence in CI

With a merge queue:

Main BranchCI SystemMerge QueueBobAliceMain BranchCI SystemMerge QueueBobAliceMain is at commit M1 ✅Main is at M2 ✅ (always green)Only Bob needs to fix his PRPR approved, enters queue (position 1)PR approved, enters queue (position 2)Test Alice's PR against M1Test Bob's PR against M1 + Alice's PRAlice ✅Bob ❌ (conflicts with Alice)Merge Alice's PRYour PR failed queue CI

The queue catches the conflict before it breaks main. Alice’s changes land. Bob gets notified. Main stays green. No one else is affected.

Without Merge QueueWith Merge Queue
Main can breakMain cannot break
Everyone is blockedOnly failing PR author is affected
Cascading rebasesNo rebases needed
CI waste on broken mainCI only runs on valid states
Trust erodes over timeConfidence in main stays high
Cycle can repeatProblem is contained

The cost of a broken main is not the time to fix it—it’s the compound disruption across your team. A merge queue eliminates this class of problem.