CockroachDB 26.2.5 stops unmergeable ranges monopolizing the queue
A merge queue could keep retrying its highest-priority range even when the merge could not succeed. The July patch adds a cooldown and reduces the interval between processing other replicas.
A queue can have enough processing capacity and still fail to make progress if it repeatedly selects work that cannot succeed. CockroachDB 26.2.5 fixes that problem in its range merge queue. The July 24 release notes describe a highest-priority range being processed repeatedly even though it could not merge. Other eligible ranges lost service, while the queue.merge.pending metric grew.
The release addresses both retry selection and processing cadence. Failed merge candidates now wait for a cooldown before being processed again. Separately, the default interval between processing replicas falls from five seconds to 200 milliseconds. Those changes solve different problems, and their relationship explains more than a general claim that range merging became faster.
I accept CockroachDB's consensus latency because its consistency guarantees are explicit. The background work maintaining its range layout matters too. A database's data placement evolves as the workload changes, and maintenance needs to make progress without spending its effort on a condition that has not changed. This fix makes that scheduling behavior more concrete.
Small ranges remain after data is deleted
The distribution-layer documentation describes CockroachDB's keyspace as a collection of ranges. A range that grows beyond the configured size splits into smaller contiguous ranges. Deleting data can leave those ranges much smaller than before, so the cluster automatically merges small neighbors when the combined size permits it.
The candidate range attempts to merge with its right-hand neighbor, whose keyspace begins where the candidate ends. The left-hand range consumes the right-hand range. This is a change to the storage distribution, not a SQL operation that combines two application tables. A table and its indexes can span multiple ranges, and range boundaries can change as their data changes.
The documentation explains why excessive fragmentation matters. Queries must contact a replica for each range involved, with a fixed coordination cost per range. More small ranges can also increase the number of machines a query contacts. Merging unnecessary small ranges can reduce that coordination work, so a merge queue that cannot serve eligible candidates can retain costs beyond its own background CPU use.
A temporary split constraint defeats immediate retries
The release gives a manually split right-hand neighbor with an unexpired sticky bit as an example of an unmergeable candidate. The boundary is intentionally protected for a period. Retrying the merge immediately does not make that protection expire sooner. The scheduler needs to recognize that the candidate cannot currently make progress and allow another candidate to run.
Previously, the blocked range could repeatedly return at the highest priority. The resulting busy loop starved other mergeable ranges. This is a scheduling failure because the queue's priority did not account adequately for the outcome of its previous attempt. High priority alone does not establish that another immediate attempt can do useful work.
Version 26.2.5 introduces kv.range_merge.cooldown, with a default of one hour, to delay reprocessing a range that could not merge. The range can become eligible for reconsideration later without monopolizing the current queue. The release does not say every failed merge needs a permanent exclusion, which would prevent progress after the original restriction changes.
A shorter interval addresses a different bottleneck
The default kv.range_merge.queue_interval falls from five seconds to 200 milliseconds. The notes explain that this lets merging keep pace with range creation. A queue that chooses useful candidates can still accumulate work if it waits too long between attempts. Reducing that delay addresses the service rate, while the cooldown addresses repeated selection of a candidate that cannot succeed.
The interval change does not establish a corresponding multiplier in completed merges or query performance. Actual work includes determining eligibility and performing merges, and the release provides no workload benchmark for this change. Its concrete claim is a shorter configured wait between processing replicas. Keeping that description precise avoids turning a default-setting ratio into an unsupported throughput result.
The pending metric also needs context. The old busy loop could inflate queue.merge.pending while starving eligible work. A growing value therefore did not identify a single cause such as insufficient hardware. The release gives another explanation, repeated attempts against unmergeable ranges, which changes how that symptom should be investigated.
Correctness fixes remain part of the patch
The same release fixes incorrect DISTINCT ON results under distributed execution when sorting spills to disk. It also fixes misordered results in particular buffered-write transactions combining range and point requests. These changes make the patch relevant beyond deployments observing merge-queue symptoms. They concern query results under execution conditions that an uncomplicated in-memory test may not reproduce.
For the merge queue itself, the substantive improvement is that a temporary obstacle no longer forces the same immediate retry while other work waits. The separate interval reduction lets eligible work be considered more often. The resulting behavior preserves automatic range maintenance while accounting for candidates whose current state makes another attempt unproductive.