enqueue/messenger-adapter
Symfony Messenger transport built on Enqueue, letting you send and receive messages through any supported broker such as AMQP or Redis. Configure the Enqueue bundle, point Messenger at enqueue://default, route your messages, and consume—with per-queue, exchange, delay, TTL, and priority options.
First, be clear about what this package actually does: it is a transport bridge for Symfony's Messenger component, not a Laravel queue driver. It lets symfony/messenger publish and consume through enqueue/enqueue, which in turn speaks AMQP, Redis, STOMP, SQS, Kafka, etc. If you are expecting Queue::push() / php artisan queue:work semantics, this is the wrong package — use laravel/sqs, predis, or php-amqplib wrappers instead. Reach for this package when you are building a Laravel app that must interoperate with services already using Symfony Messenger, or when you are scaffolding a standalone worker that shares an AMQP broker with a Symfony-based monolith.
Minimum viable install:
composer req sroze/messenger-enqueue-transport
composer req enqueue/enqueue-bundle symfony/messenger
Then create a minimal messenger.yaml (or build the transport programmatically in a service provider) — the package only wires into Messenger's framework.messenger.transports config tree, so you need that config surface. In a Laravel app you would construct it by hand rather than through the Symfony bundle:
use Symfony\Component\Messenger\Transport\TransportFactory;
use Enqueue\MessengerAdapter\EnqueueTransportFactory;
$transport = (new EnqueueTransportFactory($context))->createTransport(
'enqueue://default?queue[name]=orders',
['transport_name' => 'orders'],
new Serializer()
);
Your first real use case: publish a message from Laravel, consume it inside an existing Symfony worker (or vice versa) that shares the broker. Start by proving the round-trip with a single queue before wiring routing.
Standalone transport in a Laravel service provider. Because this package has no Laravel service provider, register a singleton in AppServiceProvider that builds the Enqueue context once and hands off a Messenger\Transport\TransportInterface:
$this->app->singleton('messenger.enqueue.orders', function ($app) {
$factory = new \Enqueue\MessengerAdapter\EnqueueTransportFactory(
\Enqueue\AmqpExt\AmqpConnectionFactory::fromDsn(env('ENQUEUE_DSN'))
);
return $factory->createTransport(
'enqueue://default?queue[name]=orders&topic[name]=orders',
['transport_name' => 'orders'],
new \Symfony\Component\Messenger\Transport\Serialization\PhpSerializer()
);
});
Decoupled worker process. Do not run the consumer inside an HTTP request lifecycle. Run a dedicated messenger:consume amqp process (or a small Laravel command that loops over $transport->get()), supervised by Supervisor, exactly as you would a queue:work worker. This is the pattern that maps most cleanly onto Laravel's operational model.
Routing across apps. On the Laravel side, wrap publishes in your own thin Publisher that composes a MessageBus with the Enqueue transport. Keep Symfony's envelope stamping out of Laravel controller code — build small adapter classes that accept your domain DTOs and convert them into Messenger messages. This keeps the coupling at a single seam.
Config DSN patterns. Put everything in the DSN: enqueue://default?queue[name]=orders&topic[name]=orders&receiveAndSendTimeout=.... The default here refers to the Enqueue context name (from enqueue/enqueue-bundle's config), not a broker — this trips people up when they expect the second segment to be the connection name.
Testing. Swap the transport for Symfony\Component\Messenger\Transport\InMemoryTransport in test environments. Because the package wraps Messenger's factory abstraction, you can bind your TransportInterface to the in-memory implementation and assert on getSent() without hitting the broker.
Migration path off Laravel Queues. If you are transitioning queue infrastructure, model each Enqueue transport as a Laravel queue connection conceptually, but drive it through Messenger. You will end up with two dispatching APIs until you migrate fully. Keep the boundary narrow — a MessagePublisher contract implemented once against Illuminate\Contracts\Queue\Queue and once against MessageBusInterface.
No Laravel integration — this is the single biggest pitfall. There is no MessengerEnqueueServiceProvider, no config publishing, no artisan command. You must bootstrap Symfony components manually. Expect to hand-write the plumbing that a Symfony bundle normally provides, and expect enqueue/enqueue-bundle docs to presume a Symfony kernel — translate them carefully.
Bundle vs. library confusion. The README assumes enqueue/enqueue-bundle is installed and provides a default context. In a Laravel-only install you will not have that bundle, so enqueue://default will not resolve unless you register a context yourself. Either bring in the bundle with a minimal Symfony kernel, or construct contexts explicitly and accept enqueue://<your-context-name>.
Serializer mismatch across services. PhpSerializer is the default but is unsafe across mixed-language or untrusted boundaries (PHP object injection). When interoperating with non-PHP consumers or with Symfony services that use Symfony\Component\Messenger\Transport\Serialization\Serializer, you must explicitly configure symfony/serializer and match message type headers. A silent deserialization failure produces an endlessly requeued message — watch for it.
Retry and DLQ behavior lives in Messenger, not Enqueue. Configure framework.messenger.transports.<name>.retry_strategy and a failure transport. Enqueue's own transport-level retry will interact with Messenger's in ways that are not obvious; pick one and disable the other. If you skip the failure transport, poison messages vanish into the void.
messenger:consume has no Laravel equivalent. You cannot use queue:restart to gracefully cycle these workers — you need SIGTERM handling and Supervisor's stopwaitsecs. Also, messenger:consume does not auto-discover Laravel-style job classes; messages are resolved by Messenger's handler locator, which you must populate manually.
Extension points are Messenger-shaped. If you need per-message headers, AMQP routing keys, or broker-specific properties, you do that via Messenger Stamp classes (e.g. AmqpStamp) which the Enqueue transport reads. Adding broker behavior outside that model means writing a custom transport — easier to subclass the factory than to bolt onto Laravel middleware.
Pin versions. The Enqueue family and the Messenger adapter have historically drifted from Symfony minor releases. The listed last release (2026-02-08) is recent, but 0.x dependents (0 in Packagist) mean you are effectively the QA. Lock symfony/messenger, enqueue/* and this adapter together, and add a smoke test that executes a full publish–consume round-trip in CI against a containerized broker.
Debugging: enable enqueue debug logging and use the broker's management UI (RabbitMQ console, Redis MONITOR) rather than PHP dump() — envelope stamps serialize into message headers and inspecting them from the broker is the fastest way to see why a message is unroutable. If messages land in the topic but never in the queue, check queue[name] vs. topic[name] binding in the DSN before touching code.
How can I help you explore Laravel packages today?