pccomponentes/messenger-retry-bundle
A Symfony bundle for Messenger that adds flexible retry handling for failed or transiently failing messages. Configure retry strategies and requeue messages through Symfony's transports and failure transport, keeping async workloads resilient without custom glue code.
Framing note: Despite the "Laravel/PHP" classification, this is a Symfony bundle, not a Laravel package. It registers into the Symfony kernel's bundle system and hooks the Messenger middleware pipeline. Laravel has no bundle registry and its queue system is a separate implementation (jobs/failed_jobs, --tries, backoff(), retryUntil()). The single most important TPM finding is that the overlap with Laravel is conceptual, not technical.
Architecture fit
symfony/messenger: it contributes a middleware into the bus pipeline and lets you declare retry strategy per transport or per message class, with exponential backoff and hand-off to a failure transport on exhaustion. Architecturally sound and idiomatic — it extends Messenger rather than replacing it.framework.messenger.transports.<name>.retry_strategy with max_retries, delay, multiplier, max_delay) plus failure-transport support. The bundle's genuine differentiator is per-message granularity and zero-boilerplate config. Everything else may be reproducible with core config. This must be validated before any adoption decision, because adopting a third-party middleware to duplicate core behaviour adds supply-chain risk for no capability gain.symfony/messenger inside Laravel is possible but you would wire the middleware manually — i.e., depend on the package's internals while discarding its bundle packaging. That is a fork in all but name.Integration feasibility
tries/backoff and a failed_jobs monitoring path; (b) treat the repo as a reference design for implementing per-job retry policy in Laravel; (c) adopt only if you already run Symfony Messenger inside Laravel and accept manual wiring.composer update can resolve a new major Symfony line. Pin it.Technical risk
retry_strategy is left enabled alongside this bundle's policy, a message can be retried by both layers — effectively max_retries² attempts. This is the failure mode most likely to reach production.Key questions for the maintainer
retry_strategy (with multiplier/max_delay) plus RecoverableMessageInterface does not — specifically, is per-message retry policy the only differentiated capability?RetryStrategy? What happens if both are configured?messenger:failed:retry and --no-retry?Stack fit
symfony/messenger + a durable transport (AMQP, Redis, Doctrine) + a configured failure transport. If that is not the stack, stop — the package is not applicable.Migration path
retry_strategy configured, what max_retries/delay/multiplier values are in play, and which handlers are non-idempotent.retry_strategy on any transport you hand to the bundle, to prevent double-retry amplification. This is a hard prerequisite, not a recommendation.Compatibility
symfony/messenger constraint against your pinned version, and check MiddlewareInterface signature compatibility across the 6.4/7.x boundary (return types were tightened in the 6→7 transition).composer update --dry-run on a scratch branch and read the resolved diff — the risk is not this package failing but this package forcing a resolver decision that moves symfony/* underneath other dependencies.Sequencing
Spike → single transport → observability (retry counters, failure-transport depth alerts) → progressive rollout → decommission any now-redundant core retry_strategy config. Keep the lockfile committed and review composer.lock diffs in PRs.
Maintenance
Support
Scaling
base_rate × (1 + max_retries). Size queues and workers against the retry ceiling, not the happy path.Failure modes
retry_strategy plus bundle policy yields multiplicative attempts and a retry storm. Mitigation: disable core retry on governed transports; assert this in config review.max_retries for validation-class exceptions, fast-fail classification.Ramp-up
How can I help you explore Laravel packages today?