symfony/redis-messenger
Redis Messenger provides Redis integration for Symfony Messenger, letting you use Redis streams as a transport for sending and consuming messages in your Symfony applications. Lightweight and fast, it's a drop-in option for async message handling.
Architecture fit. This is not a queue system — it is a transport bridge that plugs Redis Streams into Symfony Messenger's middleware pipeline (routing, retries, failure transport, stamps). That distinction drives the whole evaluation for a Laravel shop. It fits well only if two conditions hold: Redis is already a tier‑1 dependency, and the team is willing to accept Symfony Messenger's message-bus contract as the async spine for the workloads it serves. Laravel's queue is job-class-centric; Messenger is message-plus-middleware-centric. Running both is viable, but it means two async runtimes, two worker models, and two observability stories in the same codebase.
Adoption signal caveat. The 0 dependents and 217 stars are measurement artifacts: this repo is a read-only split of the symfony/symfony monorepo, and real consumption happens via symfony/messenger and FrameworkBundle. Do not read this as "unused." The corollary is more important for us: there is no package-specific issue tracker. All defects, PRs, and triage live in the Symfony core tracker under core-team ownership, with backports maintained simultaneously across the 6.4, 7.x, and 8.x lines. That is a genuine maturity positive, and it means we inherit Symfony's process — not a dedicated vendor relationship.
Integration feasibility. Mechanically straightforward (composer require symfony/messenger symfony/redis-messenger), but the Laravel-side work is the real cost: a Illuminate\Queue\Queue driver shim, a supervisor/worker wrapper around messenger:consume instead of queue:work, and event bridging so job:failed / job:released semantics and any Horizon-style monitoring have an equivalent. Estimate one engineer-week for a throwaway spike and three to four weeks for a shim hardened enough to carry production traffic.
Technical risk. The changelog is the best risk register available, and it is instructive: duplicate pending messages with batch handlers (6.4.36 / 7.4.8 / 8.0.8), ack/reject failing when a stream entry was already deleted (6.4.43 / 7.4.15 / 8.0.15 / 8.1.2), decode failures bypassing failure handling until 8.1, a crash on non-JSON-object stream entries fixed in 8.1.7, and repeated Sentinel/SSL/auth alignment fixes. These are duplication and message-loss classes, not cosmetic bugs — each one maps to a business consequence. Compounding that: delivery guarantees are inherited from our Redis persistence configuration (AOF/RDB), not from the package. Also note the extension floor moves (ext-redis ≥6.2 on 8.x, 5.x compatibility restored later), so the PHP extension version must be pinned in the container image, not just in composer.json.
Key questions for the team.
symfony/* components), and does adding this create a split-brained dependency graph?Stack fit. Best case is a Laravel app already on Redis for cache/session, PHP 8.4, and a handful of symfony/* transitive dependencies. Before committing, resolve the Symfony minor that Laravel's existing constraint set already locks, then pin this package to the matching branch (6.4 LTS, 7.4, or 8.1) — do not introduce a second, newer Symfony minor solely for the bridge. Pin ext-redis in the Dockerfile and in CI so local, CI, and prod agree.
Migration path. Do not replace Laravel's queue. Introduce the Symfony transport alongside it for one bounded, non-critical workload — outbound webhooks or notification fan-out is the usual first candidate — with the failure transport serving as the dead-letter queue. Build a read-only admin view over the failure transport early so on-call has something to look at before traffic ramps.
Compatibility. Standard redis:// and rediss:// DSNs are the low-risk path. Treat Sentinel and Cluster as phase-two with separate sign-off: that code path has absorbed a steady stream of auth/SSL/capability fixes across every branch, and RedisCluster forcing only landed in 8.1. If we depend on Sentinel for HA, that dependency is a deliberate risk acceptance, documented.
Sequencing.
messenger:consume vs queue:work delta for operators.Maintenance. Releases follow Symfony's fixed cadence and are cut on every maintained branch simultaneously. If we track a caret constraint, upgrades arrive on their schedule, not ours — budget a quarterly bump-and-regression pass, weighted toward the Redis extension compatibility churn. There is no separate security advisory stream for this package; we inherit Symfony's, which is fine but requires that someone actually watches it.
Support. Core-team and community support via the Symfony tracker, with the "looking for a backer" banner as a mild sustainability signal rather than a blocker, given Symfony's governance. There is no commercial SLA attached to the bridge itself; if the business needs one, it has to come from a Symfony support vendor or from the managed-Redis provider. Get that decision made before the pilot, not after.
Scaling. Consumer groups scale the read side horizontally and cleanly. The ceiling is Redis memory, and backpressure is weak: a slow or stalled consumer pool grows the stream unbounded unless a trim/MAXLEN policy is set and monitored. --fetch-size and batch handlers improve throughput materially, but batch handling is precisely where a duplicate-pending-messages defect lived, so validate that behavior on the exact pinned version rather than assuming.
Failure modes to design for.
Ramp-up. Two mental models must be learned (Laravel jobs vs. Messenger messages, middleware, and stamps). Plan roughly one sprint of deliberate enablement for two to three engineers, plus a written runbook and on-call walkthrough, before the pilot takes real traffic. The TPM-level recommendation: fund this as a platform experiment with a hard decision gate after the spike, not as a drop-in Laravel queue replacement.
How can I help you explore Laravel packages today?