Skip to content

PATTERN Cited by 1 source

Early queue-conflict warning

Problem

When a long-serial queue processes heterogeneous submissions — each taking minutes to hours — the feedback loop for a failed submission can span the full queue wait time. A developer submits at 9am, waits four hours behind three other requests, and learns at 1pm that one of the prior requests silently made theirs incompatible. All four hours of wait time were wasted; the context is gone; the developer now has to rebase / rewrite / coordinate from cold.

The longer the queue and the higher the inter-request conflict rate, the more acute the waste.

Solution

At queue admission time, run the same conflict check that will run at dequeue time, and warn the submitter immediately if the check detects a conflict against any currently-queued request. Do not wait for serial execution.

on_submit(request):
    for queued in current_queue():
        if conflicts(request, queued):
            warn_submitter(request, queued)
            # Optionally still admit, or reject
    enqueue(request)

Surface the warning in the same UI/channel the submitter uses to create the request, so it arrives within the creation flow rather than as an out-of-band notification later.

Canonical framing

Shlomi Noach (2023, PlanetScale):

"Schema changes may take time to run, during which more developers will want to deploy their own changes. There is a deployment queue, first come first served, that only allows a single deploy request at a time to run. When a developer submits their deploy request, their change is validated against all queued changes. This avoids the situation where the developer waits for hours in queue, only to learn the one deployment before theirs caused a conflict. PlanetScale shoots an early warning so that developers can better use their time in queue." (Source: sources/2026-04-21-planetscale-database-branching-three-way-merge-for-schema-changes)

Why it works

  • The check is cheap. Running the admission check once per submission is cheap relative to the wait time it saves. Even an O(queue_size) check is negligible against hours of developer time.
  • Context is hot. At submission time, the developer has the proposed change loaded in working memory. Rebasing, adjusting, or coordinating with the other team is inexpensive right now. An hour later, the cost is 10x.
  • No new infrastructure required. The check runs the same logic that the serial executor will run. No separate validation engine or duplicate state is needed.

Consequences

Benefits

  • Developer time preserved. Developers don't wait for doomed requests.
  • Queue throughput improved. A conflicting request that would have been rejected at dequeue can be cancelled or rebased at admission — the slot is available for the next valid request.
  • Context-aware resolution. Developers choose to rebase, coordinate, or cancel while the change is still fresh.

Costs

  • Admission-time latency. The submit endpoint now includes a check that previously ran elsewhere. Budget the check to stay within user-visible submission latency SLOs (sub-second preferred).
  • Duplication of validation logic. The conflict check runs twice — once at admission, once at execution. For correctness they must stay in sync; for cost they should share code.
  • Warning fatigue. If the queue is very active and conflicts frequent, submission warnings become noise. Needs rate-limiting, de-duplication, or severity levels.

Generalisation

The pattern is domain-agnostic. It applies to any serial queue where:

  • Submissions are expensive to wait through.
  • Conflict detection between pending requests is mechanically possible at admission time.
  • The cost of early-warning infrastructure is dominated by the cost of wasted wait time.

Examples beyond schema changes:

  • Deployment queues where N pipelines serialise their stage promotions and can conflict on shared infrastructure.
  • Build systems where queued builds might produce incompatible artefacts.
  • Reservation systems where two pending requests might conflict on the same resource.

Anti-patterns this replaces

  • "Warn at failure time" — the naive approach where the submitter only learns at dequeue. Wastes queue time and developer context.
  • "Warn asynchronously" — a background job occasionally sweeps the queue for conflicts. Better than nothing, but the warning arrives as a notification-out-of-context rather than as a submit response.
  • "Block submission on the check" — the check gates the submit button and rejects on conflict. Over-restrictive: a developer may want to submit anyway (the conflict might clear by the time they reach the head). Warnings, not rejections, preserve optionality.

When to apply

  • Serial queues with wait times in the minutes-to-hours range.
  • Conflict checks that run in milliseconds-to-seconds.
  • Developer-facing workflows where submitter time is the optimisation target.

When not to apply

  • Lightly-loaded queues where conflicts are rare and wait times short — the infrastructure cost exceeds benefit.
  • Conflict checks that are themselves expensive (full data simulations, heavy integration tests) — the check must be cheap compared to the waste it prevents.

Seen in

Last updated · 550 distilled / 1,221 read