# Idempotent Receiver

**In short:** An idempotent receiver handles the same message more than once without repeating its effect. A common way is to record the IDs of processed messages and ignore any repeat.

## Explanation

A receiver may get the same message more than once. The Idempotent Receiver pattern says to design the receiver so it tolerates this. The core question is how a consumer handles duplicate messages correctly.

**Why duplicates happen.** A client cannot always know whether its request was processed. To be sure, it sends the request again. So the server may see the same request twice.

**Recording processed IDs.** One solution is deduplication, which means detecting and skipping repeats. The consumer stores the ID of each message it has processed in the database. If a message arrives with a known ID, the consumer skips it. The IDs can live in a separate table. They can also live inside the business entities the consumer creates or updates.

**Keeping it atomic.** The consumer inserts the ID in the same database transaction as the business effect. A duplicate then violates the primary key, which is the database rule that each ID may appear only once. The handler rolls back the transaction and ignores the message.

**Saving the response.** The server can also save the response for each client and request number. On a retry, it returns the saved response without processing the request again.

**Examples in products.**
- Amazon SQS FIFO queues deduplicate by a message deduplication ID. Within a 5-minute window, only one message with the same ID is processed and delivered.
- Stripe lets clients attach an idempotency key to a request. After a connection error, the client can retry without creating a second object or applying an update twice. For API v1, Stripe stores the first response for each key and returns it on retries.

## Example

A shop sends a "charge order 1042" message with ID `m-77` to a payment service. The network drops the reply, so the shop sends the message again.

The payment service starts a transaction. It tries to insert `m-77` into its table of processed IDs. The ID already exists, so the insert fails. The service rolls back and ignores the message. The customer is charged once.

## Trade-offs

Tracking processed IDs costs storage, so you must decide how long to keep them. Stripe, for example, may prune keys after 24 hours. SQS FIFO deduplicates only within a 5-minute window. A duplicate that arrives after the window is no longer caught by that mechanism.

Storing IDs in the same transaction as the business effect keeps the two consistent. It also ties deduplication to your database.

A receiver ignores a repeated message by checking processed IDs in the same transaction.

```mermaid
sequenceDiagram
  participant S as Sender
  participant R as Receiver
  participant D as Database
  S->>R: Message m-77
  R->>D: Begin, insert ID m-77, apply effect, commit
  R-->>S: Reply (lost)
  S->>R: Message m-77 (retry)
  R->>D: Insert ID m-77 fails, roll back
  R-->>S: Ignore duplicate
```

## Checks

- The document states that receivers must tolerate receiving the same message more than once.
- The document says how duplicates are detected, for example by storing the IDs of processed messages.
- The ID record and the business effect are saved in the same database transaction.
- The retention period for processed IDs or keys is stated.

## Related

- [Messaging](https://arc.fuet.ch/concepts/integration/messaging.md)
- [Retry](https://arc.fuet.ch/concepts/tactics/retry.md)
- [Transactional Client](https://arc.fuet.ch/concepts/integration/transactional-client.md)
- [Dead Letter Channel](https://arc.fuet.ch/concepts/integration/dead-letter-channel.md)
- [Correlation Identifier](https://arc.fuet.ch/concepts/integration/correlation-identifier.md)
- [Request-Reply](https://arc.fuet.ch/concepts/integration/request-reply.md)
- [Enterprise Integration Patterns](https://arc.fuet.ch/concepts/integration/messaging-pattern-language.md)

## Sources

- [Idempotent Receiver - Enterprise Integration Patterns](https://www.enterpriseintegrationpatterns.com/patterns/messaging/IdempotentReceiver.html) — enterpriseintegrationpatterns.com, accessed 2026-11-09
- [Pattern: Idempotent Consumer](https://microservices.io/patterns/communication-style/idempotent-consumer.html) — microservices.io, accessed 2026-11-09
- [Idempotent Receiver](https://martinfowler.com/articles/patterns-of-distributed-systems/idempotent-receiver.html) — martinfowler.com, accessed 2026-11-09
- [Using the message deduplication ID in Amazon SQS - Amazon Simple Queue Service](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-messagededuplicationid-property.html) — docs.aws.amazon.com, accessed 2026-11-09
- [Idempotent requests | Stripe API Reference](https://docs.stripe.com/api/idempotent_requests) — docs.stripe.com, accessed 2026-11-09
