Workhorse
Producing work

Keyed debounce

Replace pending work under a stable key while updates continue arriving.

Debounce keeps one pending job with the latest accepted payload. PostgreSQL serializes concurrent replacements, so every caller observes one stable job identity.

const result = await queue.enqueueWithResult("search.reindex", { documentId, revision }, {
  debounce: { key: documentId, scope: "search-index", windowMs: quietPeriodMs, schedule: "reset" },
});

Choose reset to start a fresh quiet period after every replacement. Choose preserve when the first request fixes the run time and later requests should update only the payload.

result.outcome is accepted for a new job and replaced for a pending update. Once a worker owns the job, it becomes terminal, or its window elapses, PostgreSQL returns non_replaceable and keeps the accepted payload unchanged.

Only scheduled or ready jobs can be replaced. A refused replacement includes a stable reason so callers can distinguish lifecycle movement from an incompatible request.

Debounce cannot share a request with idempotency, throttle, or dependencies because each mechanism assigns a different meaning to a repeated key or immutable edge.

The result's jobId identifies the retained pending job. When replacement depends on earlier work, prerequisiteJobId identifies that immutable dependency instead of the debounce candidate.

Next


Exact debounce outcomes, limits, and lifecycle events: architecture reference.

On this page