rabbitevents/deduplication
A Laravel package that adds deduplication to RabbitEvents, helping prevent duplicate RabbitMQ messages from being processed more than once. It provides a simple layer for idempotent event handling and safer consumers.
Architecture fit: This package fits Laravel services already using rabbitevents/listener ^10.0 and a shared Laravel cache store. It addresses a real at-least-once delivery problem: duplicate handling after a lost acknowledgement or worker restart. The design is intentionally narrow and operationally sensible: deduplication state lives in the cache layer, requires no RabbitMQ plugin, and scopes IDs per queue so a message routed to multiple queues is still processed once per queue. It is not an exactly-once guarantee; listeners with side effects must remain idempotent. Teams on RabbitEvents 9.x publishers will not get deduplication because those messages carry no ID.
Integration feasibility: Low application-code integration effort: composer require rabbitevents/deduplication, configure RABBITEVENTS_DEDUPLICATION_STORE, and ensure the selected cache store exists in config/cache.php. The main integration work is environmental and operational: all workers for a queue must share the same cache store, and the store must be production-grade (redis, database, or memcached; not file/array). The package’s fail-fast behavior for a missing cache configuration is helpful for catching misconfiguration at worker start. The silent-degradation behavior when the store is unreachable is a deliberate availability trade-off but needs operational visibility.
Technical risk: Medium. The package reduces duplicate side effects but does not eliminate them. Risks include cache eviction or key expiry causing re-processing, cache outage disabling deduplication with only a warning, inconsistent cache configuration across workers, and unexpected volume of deduplication keys in the shared cache. Partial-success and worker-death scenarios are explicitly called out as “handled again,” so the package cannot replace idempotency design. RabbitEvents 9.x compatibility gaps can create a false sense of safety if some publishers remain on 9.x. The per-queue ID semantics are correct but must be understood by product and operations teams.
Key questions:
rabbitevents/listener ^10.0?Stack fit: Strong fit for Laravel teams already running RabbitEvents 10.x and Redis, database, or memcached cache stores. Weak fit for organizations still publishing with RabbitEvents 9.x, teams using non-shared cache stores, or teams expecting exactly-once semantics without idempotent listeners. The no-plugin requirement is a meaningful adoption advantage because it avoids RabbitMQ cluster changes and plugin lifecycle management.
Migration path: Treat this as an incremental reliability enhancement rather than a platform migration. First inventory RabbitEvents publishers and listeners, confirm the listener version is ^10.0, and identify any 9.x publishers that would remain outside deduplication coverage. Provision or select a shared cache store, validate capacity and retention, and install the package in staging. Exercise the two critical scenarios explicitly: lost acknowledgement after all listeners succeed, and worker death during listener execution. Then enable on a low-risk queue before expanding.
Compatibility: Confirm PHP/Laravel support, cache-store support, and rabbitevents/listener ^10.0 constraints. Ensure all workers for a given queue use the same cache store and the same RABBITEVENTS_DEDUPLICATION_STORE value. Confirm that the chosen cache store is not local to a worker and has sufficient durability/availability for production. Confirm RabbitEvents 9.x messages are either absent or accepted as non-deduplicated. Confirm that existing retry, dead-letter, and listener side-effect behavior remains unchanged.
Sequencing:
RABBITEVENTS_DEDUPLICATION_STORE.Maintenance: Low package surface area, but new operational dependencies: the shared cache store, environment configuration consistency, and cache key lifecycle. The package must track rabbitevents/listener major versions. The team must own cache retention and eviction policies because they directly affect duplicate behavior. Missing cache configuration stops workers at start, which is good for catching errors but can turn a config mistake into a deployment outage.
Support: Support and on-call teams need a runbook for the “store unreachable” warning. That condition does not drop or block messages, but it silently disables deduplication, so it is a duplicate-risk event rather than an outage. Dashboards should cover cache availability, cache latency, key volume, eviction rate, and warnings from the package. Application owners must confirm that listener side effects are idempotent; support should not assume this package guarantees single execution.
Scaling: Deduplication adds cache lookups/writes per message and stores keys per queue. Scaling worker count increases cache traffic and key cardinality, so the cache store must be sized for peak message throughput and retention. Redis is likely the simplest fit, but database and memcached have different latency, persistence, and eviction characteristics. Multi-region or multi-cluster deployments need special attention because all workers for a queue must share the same store. Benchmark before broad rollout.
Failure modes: A missing cache store config prevents worker start, which is fail-fast and visible. An unreachable cache store allows messages to be processed without deduplication and logs a warning, so duplicates are possible. Cache eviction or expiry can cause duplicate processing. Worker death during listener execution means the message is handled again by design. Lost acknowledgement after successful listener execution is the primary duplicate case the package skips. RabbitEvents 9.x messages are not deduplicated. No RabbitMQ plugin dependency reduces broker-side failure modes.
Ramp-up: Developer ramp-up is low, but operational ramp-up is moderate. Teams need to understand at-least-once delivery, per-queue deduplication scope, cache-store requirements, and the difference between “deduplicated” and “idempotent.” A TPM should require staging evidence for lost-ack and worker-kill scenarios, a cache-outage runbook, and an idempotency review before production expansion. Rollout should be canary-first, with clear success criteria: no unexpected duplicate side effects, stable cache latency, bounded key growth, and actionable warning alerts.
How can I help you explore Laravel packages today?