Merge Queue Batches
Increase your merge queue throughput and decrease your CI usage.
Mergify’s batch merging feature is a powerful tool that enhances productivity and efficiency in your development workflow. Instead of merging pull requests one by one, which can be time-consuming, especially for larger projects, batch merging allows you to combine and merge multiple pull requests at once.
The batch merging process works by setting a batch_size option on your merge
queue. This option determines the number of pull requests that Mergify will
check at the same time using your CI. If the CI validation passes, Mergify
merges all the pull requests in the batch and closes the batch pull request it
created to test.
If a failure occurs, Mergify identifies the problematic pull request(s) automatically and removes them from the queue, allowing the rest of the queue to be processed as usual (see Handling Batch Failures).
This feature is especially useful for large-scale projects with many pull requests to merge, as it can significantly reduce the time required to merge them all.
Understanding Batch Merging
Section titled Understanding Batch MergingBatch merging works by utilizing the batch_size option in your Mergify queue
configuration. This option tells Mergify how many pull requests it should try
to combine and validate at once. The batch_size can be adjusted according to
the needs of your project, with a higher number indicating a larger batch size.
For example, if you set batch_size to 3, Mergify will create a batch pull
request that includes the changes from the next three pull requests in the
queue. This batch pull request is then validated by your CI system. If all
checks pass, then the three pull requests included in the batch are deemed
ready to be merged.
queue_rules: - name: default batch_size: 3 ...This batch merging process allows multiple pull requests to be validated and merged more efficiently than if they were handled individually.
Configuring Batch Merging
Section titled Configuring Batch MergingConfiguring batch merging involves adjusting your Mergify configuration file to
set the batch_size option according to your project’s needs.
-
Open your Mergify configuration file.
-
Under
queue_rules, set thebatch_sizeoption to the number of pull requests you want to be tested together in a batch.
queue_rules: - name: default batch_size: 3 ...In the above example, batches of up to 3 pull requests will be created and tested together.
You can configure the delay that Mergify will use to wait for the batch to be
filled up using the batch_max_wait_time option.
queue_rules: - name: default batch_size: 5 batch_max_wait_time: 5 min ...With the configuration above, Mergify waits up to 5 minutes for 5 PR to enter the queue before creating a batch. This allows you to pick the right trade-off between latency and minimal CI usage.
How Pull Requests Are Grouped Into a Batch
Section titled How Pull Requests Are Grouped Into a BatchWhen batch_size is greater than 1, Mergify has to decide which pull requests
go into a batch together. It does not simply take the next few pull requests
in the queue. Instead, it groups pull requests that touch similar parts of
your codebase, so each batch is a cohesive set of related changes. This makes
batch failures cheaper to resolve: when a batch fails and has to be
split, related changes stay together and
unrelated pull requests aren’t dragged into someone else’s failure.
This is the default merge queue behavior (serial mode). Parallel mode groups pull requests strictly by scope instead. See Queue Modes.
Grouping applies these rules in order of precedence: it never overrides priority or queue order, it always keeps a stack together, and only then does similarity fill whatever batch slots remain. The sections below follow that order.
Priority comes first
Section titled Priority comes firstGrouping never overrides priority or queue order. Mergify seeds each batch with the pull request that is next to merge: the highest priority, and the oldest among equal priorities. Similarity only ever breaks ties between pull requests of equal priority: a lower-priority pull request is never pulled ahead of a higher-priority one just because it is similar. Higher-priority pull requests always fill the batch first; lower priorities are only considered once the batch still has room.
Stacks stay together
Section titled Stacks stay togetherStacks are the next firm rule, applied before similarity is considered. When a pull request depends on earlier ones still in the queue (a stack), Mergify keeps the whole stack in one batch: whenever a pull request joins a batch, its queued predecessors join with it, whether or not they share its scopes or changed directories.
This is why stack relationships take precedence over scope and directory
similarity. A predecessor joins the batch because the dependency requires it,
not because it ranked highly. The only limit is batch_size: if the stack
doesn’t fit, the dependent pull request waits for a later batch rather than
being tested without the changes it builds on.
Filling the batch by similarity
Section titled Filling the batch by similarityPriority and stacks decide what a batch must contain. Similarity decides the
rest: which of the remaining equal-priority pull requests fill the slots that
are still free (up to batch_size). Mergify adds them one at a time, ranking
every waiting candidate by three criteria applied in order, each one only
breaking the ties the previous one leaves open:
-
Scopes. The pull requests that share the most scopes with the batch are the strongest match and are grouped together.
-
Changed directories. When scopes don’t separate two candidates, Mergify compares the directories each pull request changes and prefers the one touching the same areas of the repository. On very large monorepos it automatically compares broader areas (parent directories) rather than every individual folder, so grouping stays effective whatever the repository size.
-
Queue time. If two pull requests are still tied, the one that has been waiting longest joins the batch first, keeping first-in, first-out order.
Scopes always take precedence over directories; the changed directories only decide the grouping when scopes leave it open. In practice this depends on your configuration: if you have configured scopes, pull requests are grouped by scope and the directory signal stays out of the way. If you have not, every pull request reports no scope, so that signal is a tie for all of them and grouping falls back entirely to the directories they change.
Because of this, a pull request further down the queue may join an earlier batch when it is similar to what is already there, while a closer but unrelated pull request waits for the next batch:
Here the queue order is PR #1, #2, #3, #4. PR #3 changes the same area as PR #1
(api/), so it joins PR #1 in the first batch even though PR #2 was queued
earlier. PR #2 and PR #4, which touch unrelated areas, fall into the next batch.
Merging the Batch PRs
Section titled Merging the Batch PRsBy default, Mergify creates temporary branches and batch PRs for testing batches. However, the original PRs are the ones merged, not these temporary branches. This ensures the integrity and traceability of the original pull requests.
However, there might be scenarios where you want to merge the temporary branches instead. One advantage of this is maintaining the same SHA1, which might be important for some workflows and for traceability.
Also, if you are deploying after a merge, this can also make sure that you trigger only a single deployment once a batch of pull request is fully tested and passes the CI.
There are two ways to merge the batch PR directly:
Fast-Forward
Section titled Fast-ForwardSet merge_method: fast-forward on your queue rule. When
batching is enabled, Mergify creates the batch PR as usual, runs CI on it,
and then fast-forwards the base branch to the batch PR’s head commit instead
of merging the original PRs individually.
queue_rules: - name: default batch_size: 10 merge_method: fast-forwardSee Merge Strategies: Fast-Forward for a detailed explanation of how fast-forward works in both inplace and batch-PR modes.
Merge Batch
Section titled Merge BatchSet merge_method: merge-batch on your queue rule. This merge method requires
batch_size to be greater than 1. Mergify creates the batch PR as usual, runs
CI on it, and then merges the batch PR into the base branch using the GitHub
Pull Request merge API with a merge commit. The merge commit message lists all
the pull requests included in the batch.
queue_rules: - name: default batch_size: 10 merge_method: merge-batchUnlike fast-forward, merge-batch uses the standard GitHub merge API, so it
works with branch protection settings that require pull request merges — no
bypass configuration is needed.
See Merge Strategies: Merge Batch for more details.
Handling Batch Failure or Timeout
Section titled Handling Batch Failure or TimeoutWhen a batch fails, or when the checks time out with the option
checks_timeout on, Mergify does not remove all its pull requests from the
queue. Instead, it takes additional steps to identify the problematic pull
request and remove it from the queue.
This is how it works:
-
Splitting the batch: If a batch fails, all subsequent batches are deemed to fail as well, are canceled and put back into the queue. The system splits the failed batch to isolate the problematic pull request. The size of these new batches is determined by the
max_parallel_checksparameter. By default, the batch is split into two; however, ifmax_parallel_checksis set to a value greater than 1, it dictates the number of batches the failed batch should be divided into. -
Testing the new batches: After splitting, the first new batch is immediately retested, while others are queued. If
max_parallel_checksis greater than 1, the system will also test subsequent batch split at the same time. This continues until the split is done. -
Handling the result: If the first batch split succeeds, it is merged and the next split is scheduled for testing. If the batch fails, Mergify splits this batch, going back to step 1.
-
Pin-pointing the failed batch: If a batch contains only one pull request and still fails, it is deemed to be the culprit and is removed from the queue.
Note that this system is completely automatic and there is no need to
intervene. The number of maximum splits can be controlled by
batch_max_failure_resolution_attempts.
Batch Failure Scenario Example
Section titled Batch Failure Scenario ExampleLet’s assume that we have a batch of 6 pull requests: [PR1 + PR2 + PR3 + PR4 + PR5 + PR6]. During the initial testing, Mergify first tests the batch with all
6 pull requests together.
As the batch fails, this could be due to any of the PRs or a specific
combination of them. Mergify learned that the combination
[PR1 + PR2 + PR3 + PR4 + PR5 + PR6] does not work; it now needs to test parts
of this combination.
With max_parallel_checks set to 3, the system will aim to split the batch
into 3 parts:
- First part:
[PR1 + PR2] - Second part:
[PR1 + PR2 + PR3 + PR4] - Third part:
[PR1 + PR2 + PR3 + PR4 + PR5]
The system will immediately retest the different parts since the number of splits matches the number of parallel checks allowed.
If the first part [PR1 + PR2] passes, the system will merge it.
If the first part [PR1 + PR2] fails, the system will split it again and test
each PR individually, applying the algorithm again.
If there’s a consecutive failure in the subsequent parts, the system will continue to split and isolate the problematic PR(s) and retest until the split contains a single pull request.
In-place checks (no batch PRs)
Section titled In-place checks (no batch PRs)Mergify runs checks directly on the original pull request, instead of creating temporary batch PRs, only when all of the following are true:
-
queue_rules[*].batch_size = 1 -
merge_queue.max_parallel_checks = 1 -
No two-step CI is configured (no separate
merge_conditionsbeyondqueue_conditions)
Optionally set update_bot_account to avoid in-place updates blocked by GitHub
for security reasons (for example, PRs from forks that modify workflows, or PRs
opened by other bots).
Skip intermediate results (anti-flake protection)
Section titled Skip intermediate results (anti-flake protection)Flaky tests cause intermittent batch failures that block the queue. With
skip_intermediate_results: true, Mergify stops requiring every intermediate
batch to pass: if any passing batch contains a pull request’s changes, an earlier
failing batch for that pull request is treated as transient and the pull request
still merges.
merge_queue: skip_intermediate_results: trueThis is safe because a real bug would also fail the larger batch that contains the same code; only flaky failures get bypassed. Enable it when your CI has some flakiness and you want to maximize throughput. Consider disabling it when you need every intermediate state validated for compliance, or while debugging CI and want to see all failures.
Important Considerations
Section titled Important ConsiderationsWhile using batch merging and parallel checks together can significantly speed up your merge queue processing, it’s crucial to consider the following points for an optimal setup:
Branch Protection Settings
Section titled Branch Protection SettingsBatches require the branch protection setting Require branches to be up to
date before merging to be disabled. If your team requires a linear history,
you can set the queue option merge_method: rebase.
For details on why and how to resolve this, see GitHub Rulesets Compatibility: Require Branches to Be Up to Date.
Queued PR Changes
Section titled Queued PR ChangesRemember that changes to PRs or the queue can disrupt the batch process. If a
PR is updated or changed in a way that it no longer meets the queue_rules, it
will be removed from the queue, and the order of checks will be updated. In
such cases, the process resets, and the remaining PRs are rechecked in their
new order.
Was this page helpful?
Thanks for your feedback!