Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Queue Rabbitmq Laravel Package

vladimir-yuldashev/laravel-queue-rabbitmq

RabbitMQ queue driver for Laravel. Adds a full-featured RabbitMQ backend to Laravel's queue system, supporting delayed and priority queues, exchange routing, and reliable message publishing and consumption.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and confirm your floors. v14.4.0 is a patch on the v14 line: PHP 8.1+ (PHP 8.4 is now in CI, so 8.4 is a supported target rather than a "works on my machine" claim) and Laravel 10/11/12. If you are on Laravel 12.34+ you specifically want ^14.4 — #638 fixes a compatibility break with that framework version. Nothing in this release changes the public API, so upgrading from 14.3.x is a composer update with no code changes.

composer require vyuldashev/laravel-queue-rabbitmq:^14.4
php artisan vendor:publish --tag=config      # writes config/rabbitmq.php

2. Wire up the connection. The driver is not a replacement for queue.php, it adds another connection to it. Two files are involved: config/rabbitmq.php (broker credentials, hosts, SSL, heartbeat) and config/queue.php (the queue/exchange this connection defaults to).

// config/queue.php
'connections' => [
    'rabbitmq' => [
        'driver' => 'rabbitmq',
        'queue'  => env('RABBITMQ_QUEUE', 'default'),
        'connection' => \PhpAmqpLib\Connection\AMQPLazyConnection::class,
        'hosts' => [[
            'host'     => env('RABBITMQ_HOST', '127.0.0.1'),
            'port'     => env('RABBITMQ_PORT', 5672),
            'user'     => env('RABBITMQ_USER', 'guest'),
            'password' => env('RABBITMQ_PASSWORD', 'guest'),
            'vhost'    => env('RABBITMQ_VHOST', '/'),
        ]],
        'options' => [
            'queue' => [
                'job'  => \VladimirYuldashev\LaravelQueueRabbitMQ\Queue\Jobs\RabbitMQJob::class,
                'exchange' => 'app',
                'exchange_type' => 'direct',
                'exchange_routing_key' => 'app.default',
            ],
            'heartbeat' => 0,
        ],
    ],
],
QUEUE_CONNECTION=rabbitmq
RABBITMQ_HOST=rabbitmq
RABBITMQ_VHOST=/

3. Where to look first. The published config/rabbitmq.php is small — hosts, SSL options, heartbeat. Almost everything you will actually tune day-to-day lives in the options array on the queue connection (exchange, routing key, declare flags, queue arguments). Bookmark the driver's QueueConfig/RabbitMQQueue classes in vendor/vyuldashev/laravel-queue-rabbitmq/src/Queue/ when you need the exact key names for your installed version.

4. First use case: prove the broker and credentials before touching application code. The package ships artisan commands for topology, and they fail loudly on a bad vhost, ACL, or port — which is far easier to debug than a worker that silently consumes nothing.

php artisan rabbitmq:queue:create default
php artisan rabbitmq:queue:bind default app --routing-key=app.default
php artisan rabbitmq:queue:purge default      # confirm connectivity
php artisan rabbitmq:queue:delete default      # clean up

Then flip one low-risk job (a notification, not an order) to $connection = 'rabbitmq', dispatch it, and run a verbose worker:

php artisan queue:work rabbitmq --queue=default -v

If the job never appears, the problem is topology or routing, not your job class — jump to the Gotchas section.

Implementation Patterns

One connection, many queues (the default pattern). Rather than defining a connection per queue, keep a single rabbitmq connection and vary the queue per job. onQueue() sets the queue name, and the driver resolves exchange/routing key from the options.queue block:

class SendInvoice implements ShouldQueue
{
    public $connection = 'rabbitmq';
    public $queue = 'invoices';
    public $tries = 5;
    public $backoff = [10, 60, 300];
    public $timeout = 120;
}

Multiple connections are worth it only when the broker, vhost, or credentials differ (e.g. a rabbitmq-priority connection pointing at a different exchange).

Topology as code. Declare exchanges and bindings from your deploy script or a one-off command instead of clicking in the management UI, so staging and production match:

Queue::connection('rabbitmq')->declareExchange(new Exchange('app', 'topic'));
Queue::connection('rabbitmq')->bindQueue('invoices', 'app', 'invoice.*');

Once infra owns topology (Terraform, a broker operator, a platform team), set 'declare' => false in the queue config so the app never attempts AMQP configure operations it lacks permission for.

Exchange types by intent. direct for point-to-point work queues (the common case). topic when routing keys encode domains (order.created, order.*) and consumers subscribe by pattern. fanout when the same event must reach several independent services — each gets its own queue bound to the exchange, so one consumer's backlog doesn't starve the others.

Delayed jobs and retries. delay(), later(), and $backoff all funnel into a delayed publish, which on RabbitMQ requires the rabbitmq_delayed_message_exchange plugin. Without it, delay does not behave as you expect — this is the single most common "our retries don't work" report. Configure the exchange accordingly:

'options' => ['queue' => [
    'exchange' => 'delayed',
    'exchange_type' => 'x-delayed-message',
    'exchange_arguments' => ['x-delayed-type' => 'direct'],
]],

Failure handling — pick one path, not both. Laravel's failed-job provider (the failed_jobs table, queue:failed, queue:retry, queue:forget) is the operator-friendly default and is what your on-call runbook probably assumes. The alternative is broker-side dead-lettering: 'reroute_failed' => true with failed_exchange/failed_routing_key, or x-dead-letter-exchange in the queue arguments. Enabling both means every failure is recorded twice and someone eventually replays a message twice.

Priority and durability via queue arguments. Priority queues (x-max-priority) and quorum queues are configured by passing queue arguments in the connection config — worth knowing before you promise an SLA on a queue type the broker wasn't told to create.

Long-running consumers. Under supervisor you generally run core Laravel workers (queue:work rabbitmq) because they honour $tries, $timeout, --max-jobs, and queue:restart. Reach for the package's rabbitmq:consume when you need consumer-side control the core worker doesn't expose (explicit exchange/routing-key binding, its own memory/sleep/tries flags). Whichever you choose, use queue:work, not queue:listen — listen boots a fresh process per job and destroys throughput.

Deploy loop. php artisan queue:restart after every deploy (supervisor restarts pick up new code); scale by adding workers, not by raising prefetch to hide a slow job — prefetch just moves the backlog from the broker into one worker's memory.

Testing. Queue::fake() covers dispatch assertions in unit tests, but it asserts nothing about AMQP routing. Keep a small integration suite that runs against a real rabbitmq:3-management service container in CI, publishes, consumes, and asserts the job ran — that's the only layer that catches a wrong routing key or an undeclared exchange.

Gotchas and Tips

  • No exchange configured ≠ no exchange. With no exchange set, messages go to the AMQP default exchange with the queue name as the routing key. It looks like it works in dev, then breaks the moment someone binds a consumer to a named exchange. Always set exchange and routing_key explicitly in anything beyond a spike.
  • The vhost must start with /. 'vhost' => 'staging' fails; '/staging' works. '/' is the default vhost and is easy to omit by accident.
  • Delayed retries need the broker plugin. If $backoff/delay() seem ignored, check rabbitmq-plugins list on the broker before you touch application code.
  • queue:flush and queue:clear are DB-driver features. They do nothing useful here; use php artisan rabbitmq:queue:purge <queue>.
  • Duplicate delivery is normal. RabbitMQ is at-least-once: a worker killed between handling and ack gets the message again. Make jobs idempotent (guard on an order state, use ShouldBeUnique-style checks) rather than assuming exactly-once. This matters more with quorum queues and aggressive --timeout values.
  • Set --timeout below whatever the broker or your job's own HTTP clients expect, and don't let a job outlive its heartbeat. A worker that hangs blocks the queue for everyone behind it.
  • Use AMQPLazyConnection. It defers connecting until the first publish/consume, which keeps web requests that never touch the queue from opening (and leaking) AMQP sockets.
  • Credentials work at the CLI but not in the worker (or vice versa) usually means ACL permissions: consuming needs read, declaring needs configure/write. In production, prefer 'declare' => false and provision topology out-of-band.
  • Keep payloads small. Serialised models with large attribute sets bloat messages and memory; pass an ID and re-read in the job. Payloads also live in the broker, so sensitive data outlives your app's request cycle.
  • Debugging order that actually saves time: (1) exchange and routing key match between publisher and binding, (2) queue exists and shows a consumer in the management UI, (3) ready count rising means no consumer is bound or the consumer is subscribed to a different queue name, (4) unacked climbing means jobs are hanging — look at --timeout and prefetch, not at the broker.
  • --queue is a comma-separated list of queue names, resolved by the driver per name. Queues that don't exist (and aren't declared, because declare is off) simply never yield messages — a silent, confusing "worker runs but does nothing".
  • Extension points before forking: the job class is swappable via options.queue.job, the connection class via the connection key, and Laravel's Queue::before/after/failing events plus JobProcessing/JobProcessed give you metrics and tracing without editing the package. Override the job class only when you genuinely need custom AMQP property handling.
  • On this release specifically: v14.4.0 has no behavioural or config changes, so it needs no migration work — but if you were pinning 14.3.* and had issues booting under Laravel 12.34, the fix is in #638, and PHP 8.4 users get a tested target for the first time. Pin ^14.4 and re-run your integration queue test once after the bump.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console