Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Integration idempotent receiver: the metadata key is not the business commit

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

The idempotent receiver interceptor detects repeated messages, but its default metadata store is process-local and its decision is separate from business state.

Choose the duplicate identity

A parcel scan from a handheld device needs a stable event ID, tenant ID and source revision. A timestamp header is not a safe business key: redelivery often has a new timestamp. MetadataStoreSelector can use an explicit key and a shared ConcurrentMetadataStore. By default, the selector's in-memory state disappears on restart, and a rejected message can still reach the handler marked as duplicate unless discard or rejection behavior is configured.

Close the atomicity gap

If the metadata store marks an ID seen and the business database transaction then rolls back, a retry can be incorrectly dropped. Put the dedup key and business write in one database transaction when that guarantee matters, using the unique-key consumer pattern. The interceptor remains useful as an early filter, but it is not proof of exactly-once effects across two stores.

Verify replay

Deliver event parcel-47 twice, restart the process, deliver it again, and compare rows and side effects. Then fail after metadata acceptance but before the business commit. This tests the gap that a duplicate-only unit test misses. The interceptor configuration below is an implementation sketch; connect it to a durable metadata store before using it for restart behavior.

Implementation sketch

Java
@Bean
IdempotentReceiverInterceptor parcelDedup(ConcurrentMetadataStore store) {
    MetadataStoreSelector selector = new MetadataStoreSelector(
        message -> message.getHeaders().get("tenantId") + ":"
                + message.getHeaders().get("parcelEventId"), store);
    return new IdempotentReceiverInterceptor(selector);
}

Cost and verification

Each acceptance check adds metadata I/O if the store is shared. Keys need retention and a deletion policy; deleting them too early permits old redeliveries to run again.

Common Mistakes

  • Do not use a changing timestamp as the duplicate identity.
  • Do not assume rejected messages are discarded unless that behavior is configured.
  • Do not treat a metadata-store write as atomic with a separate business database commit.

Read next

Spring consumer deduplication: commit the event ID with the mutation, Spring Integration queue: bound memory and choose a real message store, Spring Kafka duplicate delivery: let a unique event ID decide the second debit, Spring Integration poller: include receive and handler in the failure boundary.

spring
spring-boot
integration
integration-idempotent-receiver
Storage details