Introducing Trunk's AI DevOps Agent: Root cause and automatically fix CI failures Join the waitlist
Merge Queue

Outgrowing GitHub Merge Queue

Why Trunk is the Better Choice

September 3, 20257 min read
Sam Gutentag
Sam Gutentag

When your team starts hitting the limits of GitHub's native merge queue, it's time to level up. This post breaks down why teams benefit from switching from GitHub's merge queue to Trunk's more sophisticated solution and how to make the transition smoothly.

Understanding the Foundation: What Problems Do Merge Queues Solve?

The Traffic Jam Analogy

Think of your main branch like a busy highway during rush hour. Without traffic control (merge queue), everyone tries to merge at once, causing accidents (broken builds) and traffic jams (conflicting PRs).

The core problem: When Jack renames function foo() to bar() and Jill adds code that calls foo(), both PRs pass tests individually but break main when merged together. This is like two cars simultaneously entering a highway merge lane, which is not ideal.

Why Basic Branch Protection Falls Short

GitHub's "require branches to be up to date" setting is like having a stop sign at every merge. It works, but creates a terrible developer experience:

  1. Wasted CI: Tests run on stale code that will never be merged

  2. The Rebase Race: Developers constantly rebase to stay current

  3. Developer Frustration: Hours spent on manual conflict resolution

GitHub Merge Queue: A Good Start, But Limited

How GitHub's Solution Works

GitHub's merge queue acts like a single-lane highway with a traffic controller (GitHub merge queue documentation):

  1. Sequential Processing: PRs enter a single queue (first-in, first-out)

  2. Predictive Testing: Creates temporary merge_group branches containing your PR + all PRs ahead of it

  3. Automated Merging: If tests pass, merges automatically

Step-by-Step Example

1PR A: Renames foo() to bar()
2PR B: Adds new code calling foo()
3
4GitHub's merge queue:
51. Creates branch: main + PR A
62. Tests pass ✅
73. Creates branch: main + PR A + PR B
84. Tests fail ❌ (foo() doesn't exist)
95. Removes PR B, merges PR A
106. PR B author must fix and resubmit

Here's how this process flows:

The Limitations Start to Show

Analogy: GitHub's merge queue is like a highway with only one toll booth. It works fine for small teams, but the line gets impossibly long as you scale.

1. Single Queue Bottleneck

  • All PRs wait in one line, regardless of whether they're related

  • A documentation fix waits behind a complex backend refactor

  • Result: Unnecessary delays for independent changes

2. CI Cost Inefficiency

  • Every PR runs CI twice: once on the branch, once in the merge group

  • No batching to reduce total CI runs

  • Impact: Higher costs and longer wait times

3. Limited Visibility

  • When a PR fails in the merge group, spending time debugging is painful

  • No clear indication of what's being tested when

  • Why this matters: Developers need visibility to stay productive

4. Configuration Rigidity

  • Build concurrency capped at 100 (GitHub limitations)

  • Limited merge strategies

  • Tradeoff: Simplicity comes at the cost of customization


Trunk Merge Queue: The Enterprise-Grade Solution

The Highway System Analogy

If GitHub's merge queue is a single-lane highway, Trunk is a modern interstate system with:

  • Multiple express lanes for different types of traffic

  • Smart routing based on destinations (code dependencies)

  • Optimized traffic flow with batching and parallel processing

Key Advantages and How They Work

1. Parallel Queues: Multiple Express Lanes

How it works: Trunk analyzes each PR's "impacted targets" (which parts of the codebase it changes) and creates dynamic parallel queues (parallel queues documentation).

1# Example with 4 PRs:
2
3PR A: Changes backend API (affects: backend)
4PR B: Updates CSS styles (affects: frontend)  
5PR C: Updates README (affects: docs)
6PR D: Changes both API and UI (affects: backend, frontend)
7
8Traditional queue: A → B → C → D (all wait in line)
9Trunk parallel:   A ——→ merge    (backend queue)
10                  B ——→ merge    (frontend queue)  
11                  C ——→ merge    (docs queue)
12                  D waits for A & B, then merges

Why this matters: Independent changes don't block each other. Your docs fix doesn't wait for a complex backend refactor.

Setup step: Configure your build system (Nx, Bazel, etc.) to report impacted targets via Trunk's API.

The difference in efficiency is dramatic:

2. Batching: Bulk Processing for Efficiency

How it works: Instead of testing PRs one by one, Trunk groups compatible PRs into batches and tests them together (batching documentation).

1# Without batching:
2PR1Test (10 min)Merge
3PR2Test (10 min)Merge  
4PR3Test (10 min)Merge
5Total: 30 minutes, 3 CI runs
6
7# With batching (batch size = 3):
8PR1 + PR2 + PR3Test (10 min)Merge all
9Total: 10 minutes, 1 CI run (70% time savings!)

Configuration options (advanced settings guide):

  • Target Batch Size: How many PRs to group (1-100)

  • Maximum Wait Time: How long to wait for the batch to fill up

Failure handling: If a batch fails, Trunk automatically bisects to find the problematic PR:

1Batch [PR1, PR2, PR3] fails →
2Test [PR1, PR2]Pass
3Test [PR3]Fail
4Result: PR1 and PR2 merge, PR3 gets kicked from queue

This batching process dramatically improves efficiency:

3. Optimistic Merging: Smart Traffic Flow

The concept: Instead of a strict first-in-first-out queue, Trunk can merge PRs that are ready, even if earlier PRs are still testing.

Example scenario:

1Time 0:00 - PR A starts testing (estimated 20 min)
2Time 0:05 - PR B starts testing (estimated 10 min)
3Time 0:15 - PR B finishes ✅, PR A still testing
4Result: PR B merges immediately, doesn't wait for PR A

Why this works: If PR B was tested against "main + PR A", it's safe to merge both when PR A eventually completes.

Here's the timeline comparison:

4. Anti-Flake Protection: Dealing with Unreliable Tests

The problem: Flaky tests cause good PRs to fail randomly, wasting developer time.

Trunk's solution:

  • Automatically detects patterns in test failures

  • Quarantines flaky tests

  • Provides retry logic for intermittent failures

Configuration: Set retry limits and flake detection thresholds to match your reliability needs.

Advanced Features That Scale

Pending Failure Depth

Allows PRs to continue testing even if earlier PRs fail, up to a configured depth (see advanced settings). Like having dedicated lanes for different vehicle types on a highway.

Smart Prioritization

Control the order PRs are tested and merged using Trunk's priority system (PR prioritization documentation):

How it works: Set priority levels when submitting PRs to the queue:

1# Command-line prioritization options
2/trunk merge --priority=0    # Urgent Priority - Interrupts running jobs immediately
3/trunk merge --priority=10   # High Priority- Goes ahead of medium/low priority PRs  
4/trunk merge --priority=100  # Default Priority
5/trunk merge --priority=200  # Low Priority - Goes to back of queue

Priority Levels and Behavior:

  • urgent (0): Interrupts currently running jobs and starts testing immediately

  • high (10): Jumps ahead of lower-priority PRs but won't interrupt running tests

  • medium (100): Default priority for all PRs

  • low (200): Goes to the back of the queue

Real-world example:

1# Production hotfix that needs immediate deployment
2/trunk merge --priority=0
3
4# Feature PR during normal development  
5/trunk merge  # Uses default medium priority
6
7# Dependency update that's not time-sensitive
8/trunk merge --priority=200

Why this matters: Unlike GitHub's basic queue jumping (which rebuilds everything), Trunk's prioritization is surgical, it only interrupts when necessary (urgent priority) and otherwise intelligently orders the queue.

Here's how priority affects queue ordering:

Conclusion: Building for Scale

GitHub's merge queue was a great first step, it solved the basic problem of keeping main branch stable. But as teams scale beyond 20-30 developers, the single-queue limitation becomes a significant bottleneck.

Trunk merge queue represents the next evolution: parallel processing, intelligent batching, and enterprise-grade features that scale with your team. The migration process is straightforward, and the productivity gains are immediate.

Bottom line: If you're spending more time managing your merge queue than it's saving you, it's time to upgrade. Trunk's parallel queues, batching, and advanced features transform merge queues from a necessary evil into a competitive advantage.


Ready to make the switch? Get started at trunk.io and see the difference Trunk Merge Queues can make for your team.

Try it yourself or
request a demo

Get started for free

The DevOps Assistant
for self-healing CI