- A message is published to QStash.
- QStash attempts to deliver the message to the destination.
- Before the request is completed, the QStash server shuts down unexpectedly.
- When the server restarts, it cannot determine the final delivery status of the message.
- To avoid losing the message, QStash delivers it again.
True exactly-once delivery cannot be guaranteed in distributed systems under all failure scenarios.Most production messaging systems therefore use at-least-once delivery together with idempotent handlers to prioritize reliability and prevent message loss.To learn more about the underlying coordination challenge, see the Two Generals’ Problem.
1. Use an idempotency key
Because duplicate deliveries can occur, you can use an idempotency key to ensure that the an operation is executed only once. Each QStash message includes a uniqueUpstash-Message-Id header, which you can use for this purpose.
For example, if your handler updates a database record, you can store the Upstash-Message-Id in the database along with the record. Before processing a message, you can check if the Upstash-Message-Id has already been processed. If it has, you can skip processing the message again.
An example implementation using Redis is shown below:
api/handler/route.ts