Visibility Timeout and Message Lifecycle
~8 min read
How SQS prevents (most) duplicate processing while still guaranteeing at-least-once delivery.
When a consumer calls ReceiveMessage, SQS doesn't delete the message immediately — instead, it becomes invisible to other consumers for the queue's configured Visibility Timeout (default 30 seconds, configurable up to 12 hours). This gives the receiving consumer a window to finish processing before any other consumer could pick up the same message.
If the consumer finishes successfully within that window, it calls DeleteMessage, permanently removing it from the queue. If the consumer crashes, times out, or simply never calls DeleteMessage (perhaps due to an unhandled error), the message automatically becomes visible again once the timeout expires — ready to be received and processed again, by the same or a different consumer.
This mechanism is what gives SQS its 'at-least-once' delivery guarantee: under normal conditions, a message is processed exactly once, but if a consumer legitimately takes longer than the visibility timeout, or crashes right after finishing but before calling delete, a duplicate delivery can occur — which is why consumer logic must be written to handle being invoked more than once for the same message without causing incorrect duplicate side effects (idempotency).
💬 Deep Dive with AI
Key points
- •ReceiveMessage doesn't delete a message — it becomes temporarily invisible for the visibility timeout duration
- •DeleteMessage after successful processing permanently removes it
- •No delete before timeout expiry means the message becomes visible again for reprocessing
- •This mechanism is the source of SQS's at-least-once (occasionally more) delivery guarantee