> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/code-repository/use-harness-code/pull-requests/merge-queue.md).

# Merge Queue

How Merge Queue validates the combined result of queued pull requests before they land on a protected branch in Harness Code.

A pull request can pass every required check and still break the branch it merges into. The checks ran against the target branch as it looked when the pull request was opened, and another pull request has landed since. Merge Queue removes that gap.

Merge Queue holds eligible pull requests in an ordered queue, builds a speculative commit that combines the target branch with the queued changes, runs the required checks against that commit, and fast-forwards the target branch to the commit that passed. Nothing merges on the strength of a check that ran against an older branch.

{% hint style="info" %}
**The tested commit is the merged commit**

The commit Harness CI validates is the same commit that lands on the target branch. There is no rebase, no second merge, and no re-interpretation of the result after the checks pass.
{% endhint %}

## What you will learn from this topic

This topic explains the model behind Merge Queue so you can decide whether a repository needs one and read its behavior correctly once it is enabled:

* **The integration gap:** why two individually green pull requests can break a branch when they merge in sequence.
* **Speculative commits:** how Harness Code builds the commit that CI validates.
* **Queue states:** the stages a queue entry moves through between admission and merge.
* **Batching and concurrency:** the settings that decide how much CI a queue consumes.
* **Repository fit:** which repositories gain from a queue, and which do not.

## How Merge Queue works

### The integration gap

Two pull requests open from the same commit on `main`. Each one passes its checks against that commit. The first merges, and `main` moves on. The second then merges on the strength of checks that never saw the first change, and the branch breaks.

The two changes do not have to touch the same lines. Git reports no conflict, and the failure appears only when the combined result runs. Common shapes:

* One pull request changes an API signature while another adds a caller that uses the old one.
* Two pull requests each raise resource consumption, and together they cross a shared limit.
* One pull request changes configuration semantics that another still depends on.
* Two schema changes are each valid alone and invalid together.

Requiring every pull request to be up to date before it merges narrows the gap, but it moves the cost onto contributors. Every merge invalidates every other branch, so contributors rebase, wait for the checks again, sometimes re-collect approvals, and repeat. On a busy repository with slow checks, that loop can run longer than the work itself.

Merge Queue centralizes the coordination instead. A contributor establishes that the pull request is ready, and the queue validates it against the correct branch state when its turn arrives.

### Speculative commits

When a pull request enters the queue, Harness Code creates a commit that represents the target branch as it would be if everything ahead of that pull request in the queue merged first. That commit is the speculative commit, and it is what CI clones and tests.

For two entries added in order, the chain builds like this:

```mermaid
flowchart LR
    M0["main"] --> MA["main + first pull request"]
    MA --> MB["main + first and second pull requests"]
```

If the checks pass on the deeper commit, the combined result containing both pull requests is proven, and Harness Code fast-forwards `main` to that commit. A deeper commit that passes also clears the shallower entries already contained in its history.

The full path from admission to merge:

```mermaid
flowchart TD
    A["Pull request is added to the queue"] --> B["Harness Code creates the speculative commit"]
    B --> C["MergeQueue webhook starts the pipeline"]
    C --> D["CI clones and tests the speculative commit"]
    D --> E["The pipeline reports the required check on that commit"]
    E --> F["Harness Code fast-forwards the target branch"]
```

If a required check fails, the affected pull request leaves the queue. Entries behind it are recalculated against the new order and tested again.

### Queue states

An entry moves through four states between admission and merge. The state tells you whether an entry is waiting on Harness Code, waiting on capacity, or waiting on CI:

| State                | What it means                                                            |
| -------------------- | ------------------------------------------------------------------------ |
| `merge_pending`      | Harness Code is building the speculative commit for the entry            |
| `checks_pending`     | The speculative commit exists and the entry is waiting for a check slot  |
| `checks_in_progress` | The entry leads its group, and CI is validating its commit               |
| `merge_group`        | The entry follows a leader and is covered by the leader's checked commit |

An entry that conflicts while its speculative commit is built leaves the queue before any checks start, so it consumes no CI.

### Batching and concurrency

Three repository settings decide how much CI a queue consumes and how much work one failure costs:

* **Merge group size:** the maximum number of consecutive pending entries that one speculative commit validates. The last entry in the group leads it, and every member shares the leader's checked commit. A larger group means fewer pipeline runs, and one failure removes work for the whole group. The value is an upper bound rather than a guarantee, because entries are grouped only when they are pending in the same scheduling pass.
* **Checks concurrency:** the maximum number of groups that can have checks running at the same time. A higher value drains the queue faster and consumes more CI capacity in parallel.
* **Maximum check duration:** the deadline for a group's checks. An entry that passes the deadline is removed. Cleanup runs periodically, so removal can happen at the deadline plus roughly three minutes.

### Branch and pull request restrictions

Merge Queue owns the target branch while it is active, so several operations that are ordinarily available are restricted:

* **Target branch:** direct pushes, direct merges, and branch deletion are blocked. The queue is the only route in.
* **Queued source branches:** the source branch of a queued pull request is frozen. Remove the pull request from the queue before you push to it, rebase it, retarget it, or delete it.
* **Cumulative conflicts:** a pull request can be clean against the current target branch and still conflict with an earlier queued entry. Harness Code removes it and reports the conflict.
* **Obsolete work:** a change in queue order cancels the CI run for the speculative commit that no longer reflects the queue.

## When to use Merge Queue

A queue adds latency and CI cost to every merge, so it earns its place where concurrent changes create real risk to a branch that matters.

### Repositories that benefit

Consider Merge Queue when several of the following are true:

* The repository takes many merges each day.
* Multiple teams contribute to it.
* Checks run long enough that they go stale before a pull request merges.
* The repository is a monorepo, or its components are tightly coupled.
* A broken default or release branch is expensive to recover from.
* Individually green pull requests have broken the branch before.
* Contributors rebase mainly because someone else merged first.

### Repositories that do not need a queue

Leave Merge Queue disabled when:

* The repository takes few merges.
* A small team already coordinates merges directly.
* Changes are mostly independent of each other.
* A broken branch is cheap to repair.

{% hint style="warning" %}
**Stabilize flaky checks first**

A flaky required check removes valid pull requests from the queue and forces the entries behind them to be rebuilt and tested again. Make the required checks reliable before you enable Merge Queue on a repository.
{% endhint %}

## Next steps

Go to [Set Up Merge Queue](/code-repository/use-harness-code/pull-requests/merge-queue/set-up-merge-queue.md) to configure the branch rule, trigger, and pipeline for a repository. Go to [Merge PRs](/code-repository/use-harness-code/pull-requests/merge-pr.md) to compare the merge strategies available outside the queue, and go to [Auto-merge pull requests](/code-repository/use-harness-code/pull-requests/auto-merge-pr.md) to merge a single pull request as soon as its own requirements are met.

{% @harness-feedback/feedback module="code-repository" pagePath="code-repository/use-harness-code/pull-requests/merge-queue" %}
