-
Type:
Improvement
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Query Execution
-
Query Execution
-
QE 2026-08-17
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Problem
The write-conflict retry backoff in the plan-executor yield path (PlanExecutorImpl and the express executor) sleeps 0ms for the first 4 attempts and then steps through fixed tiers (1/5/10ms, 100ms after 100 attempts). Under a conflict storm on a hot document, retriers re-execute almost immediately, burning CPU and inflicting conflicts on each other: each retry execution is itself a source of conflicts for the other contenders. On an over-offered Atlas M50 (write_conflicts_under_heavy_pressure_locust), the retry herd drives ~7,500-8,000 writeConflicts/s and starves baseline traffic (baseline write goodput 2,926/s of a 10k offered load, individual write latencies up to 60+ s).
Change
Replace the stepped schedule with an exponential one, in a QE-owned header (src/mongo/db/query/write_conflict_backoff.h) used only by the two plan-executor call sites:
* Attempts 1-3 sleep 0/1/2ms so short contention resolves without a meaningful wait.
* From attempt 4 the base sleep starts at 8ms and multiplies by 4 per attempt, capped at 256ms; full jitter in [base, 2*base].
* The sleep honors interrupts and the operation deadline (opCtx->sleepFor).
* Runtime knobs: internalQueryWriteConflictBackoffRampStartMs (0 = kill switch, routes to the legacy stepped backoff), RampGrowthFactor, CapMs; plus an off-by-default contention-adaptive skip (WaitersThreshold, MaxAttemptSkip).
* internalQueryEnableWriteConflictBackoffWithoutTicket defaults to true: with sleeps up to 256ms, holding an execution ticket through the sleep starves admission.
Measured results (sys-perf write_conflicts_under_heavy_pressure_locust, Atlas M50, n=3 per arm)
* Retry attempts -31%; writeConflicts/s 7,459 -> 5,549.
* Baseline write goodput 2,926 -> 8,152/s; p50 195 -> 140ms.
* Conflict-op starvation tail collapses: max 40s -> ~10s, p99.9 halved. Cost is the conflict mid-tail (p95 ~1s = the schedule's own cumulative sleep).
* Combined with execution control (EC-only profile): baseline write goodput 12,662/s, both goodput scores 10, hot-doc completions +36% vs stock EC-only, conflict max 112s -> 48s, zero rejections.
Scope
Only the query-execution yield path changes (src/mongo/db/query/, src/mongo/db/exec/express/). The writeConflictRetry helper used by the write paths (including timeseries bucket inserts) keeps the legacy backoff.