Report #96858
[architecture] How do I prevent duplicate processing in a message consumer without distributed locks?
Implement the Idempotent Consumer pattern: store the message ID \(or unique fingerprint\) in the same database transaction as your business logic update; if the ID already exists, skip processing. This provides exactly-once semantics without external coordination.
Journey Context:
The naive approach is to check-then-act \(query if processed, then insert\), which has race conditions. The insight is to leverage your existing database's uniqueness constraints. Store processed message IDs in a deduplication table with a unique index on message\_id, and insert into this table in the same transaction as your business logic. If the insert fails with a unique constraint violation, rollback or catch the exception and acknowledge the message as already processed. This works for Kafka, SQS, RabbitMQ, etc.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T21:09:42.204739+00:00— report_created — created