For Node.js delayed background task scheduling, publish the task with an explicit delay, then make the consumer idempotent before adding retries; that is the safest shape for draining a rate-limited media worker pool. The delay controls eligibility. It doesn't turn at-least-once delivery into exactly-once processing.
Short answer: put the delay in the publish parameters, carry a stable job ID, and have the worker record completion in durable storage before acknowledging the message. For a long-running job, use a scheduler only to trigger the queue; let the worker do the work.
What does delayed execution actually guarantee?
It guarantees that a message should not become eligible before its delay has elapsed. It does not promise an exact execution timestamp, and it does not prevent a second delivery after a timeout or worker restart.
Consider a media service that generates a thumbnail 90 seconds after an upload. The publisher sends a small job with a stable ID.…