Idempotent Consumer
A message consumer whose effect is the same whether a message is processed once or many times, which is what makes at-least-once delivery safe.
Since at-least-once is what messaging systems actually offer, and duplicates are a certainty rather than an edge case, the consumer's design is where correctness is won.
Three implementations, in increasing robustness. Natural idempotence — the operation is a set rather than an increment, so repeating it changes nothing. This is the cheapest and is often available if the message carries the new value rather than a delta. Deduplication on a message identifier, where processed identifiers are recorded and re-arrivals are dropped; this needs the record and the effect to be committed atomically, or a crash between them reintroduces the problem. Conditional writes using a version or expected-state check, so a repeat is rejected by the database rather than by the application.
The detail that decides whether deduplication works: the identifier must be stable across retries. A producer that generates a fresh identifier on each retry has defeated the mechanism entirely, which is a surprisingly common defect and is invisible until a duplicate matters.
The other real constraint is the dedup window. Storing every identifier forever is not viable, so there is a retention period, and a duplicate arriving after it will be processed. That window should be set against the longest plausible retry or replay delay, and stated explicitly rather than left as a default.