Skip to content

About

Native Rust RabbitMQ transport for PHP and Laravel workers — at-least-once, auto-recovering, PIE-installable.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

 

History

1,025 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Rabbit RS

Keep writing PHP. Let Rust handle RabbitMQ.

CI Release Codecov Quality Gate CodSpeed Packagist PHP License: MIT

Rabbit RS is a native RabbitMQ runtime for PHP and Laravel workers, designed to stay alive. Your application keeps using Laravel's standard queue API; Rabbit RS handles connections, publisher confirms, recovery, and long-running consumption in a native Rust runtime.

The product is built around one feature: the long-running consumer — a worker that multiplexes many queues per broker connection, survives broker restarts and network failures, and keeps settling deliveries through recovery without manual intervention. A supervised fan-out command runs one worker per connection to span vhosts and brokers.

Delivery is at-least-once. Once a message is accepted into the confirmed delivery path, silent loss is unacceptable; duplicates are permitted and must remain measurable.

Quick start

Step 1 — Install the native extension:

pie install goopil/rabbit-rs-native

Step 2 — Install the Laravel queue driver:

composer require goopil/rabbit-rs-laravel

Step 3 — Configure the connection:

Add a rabbit-rs connection to config/queue.php (one connection = one broker = one native pool):

'connections' => [
    'rabbit-rs' => [
        'driver' => 'rabbit-rs',
        'queue' => env('RABBIT_RS_QUEUE', 'default'),
        'hosts' => env('RABBIT_RS_HOSTS', '127.0.0.1:5672'),
        'username' => env('RABBIT_RS_USERNAME', 'guest'),
        'password' => env('RABBIT_RS_PASSWORD', 'guest'),
    ],
],

Configuration is connection-first — broker, credentials, routes, safety mode, and worker profile all live on the queue connection. The full reference (every key, defaults, validation, and the safety modes) is packages/laravel-queue/docs/reference.md. Optionally publish the cross-cutting defaults:

php artisan vendor:publish --tag="rabbit-rs-config"

Step 4 — Publish and consume a job:

// app/Jobs/ProcessOrder.php
class ProcessOrder implements ShouldQueue
{
    use Dispatchable, Queueable;

    public function __construct(public int $orderId) {}
}

// Dispatch
ProcessOrder::dispatch(42);
# Consume
php artisan queue:work rabbit-rs
# or the supervised fan-out across every rabbit-rs connection:
php artisan rabbit-rs:work

No extra configuration required: pop the queue directly — it is the connection's queue key — or declare more queues under the subscriptions escape hatch. A pop addressed to one queue of a multi-queue connection gets a dedicated single-queue consumer, so it never draws from the sibling queues (see packages/laravel-queue/docs/reference.md).

What it does

  • Long-running consumer — one worker multiplexes subscriptions across many queues on its connection and survives broker restarts without manual intervention
  • At-least-once delivery — publisher confirms and mandatory routing enabled by default; every publish is tracked to ACK, return, or timeout
  • Deterministic recovery — connection, channels, exchanges, queues, bindings, QoS, then consumers, in a fixed order
  • Weighted-fair scheduling — proportional delivery shares across subscriptions by weight
  • Connection-generation-aware tokens — stale ACKs are rejected so RabbitMQ redelivers
  • Bounded replay buffer — unconfirmed publications survive connection recovery in bounded memory, replayed with the same message_id
  • Multi-broker fan-out — a vhost owns a distinct AMQP connection; define one connection per broker/vhost and rabbit-rs:work supervises them all
  • Auto-scaling supervisor — rabbit-rs:work grows its fleet under load and releases idle workers, driven by management-API queue depth (--min-workers/--max-workers), with one-shot --once/--stop-when-empty modes for CI drains
  • Octane lifecycle — flush, reload, and stop hooks prevent channel leaks
  • No unsafe Rust — #![forbid(unsafe_code)] across the entire workspace

On the lab consumption workload (transport harness, unit pop+ack — php-amqplib pulls one basic_get per message, rabbit-rs runs a pushed subscription with prefetch 64 and manual acks; the publish side is blind on both), rabbit-rs reaches 12 963 ops/s against 2 255 ops/s for php-amqplib on the same session, interleaved runs (10 000 msgs/round × 10 rounds), with 0 losses and 0 duplicates in every archived run. Harness, methodology, and archived results: benchmarks/README.md; the numbers above are from benchmarks/results/round-2-rebench/README.md.

Support contract

Dimension Support
PHP 8.2, 8.3, 8.4, and 8.5 — NTS and ZTS on Linux; NTS only on macOS (ZTS deferred)
Laravel 12 and 13 (for the Laravel queue driver)
SAPIs CLI, PHP-FPM, and Octane (FrankenPHP, RoadRunner, Open Swoole, Swoole)
RabbitMQ 4.2.9 or newer (the CI lab runs 4.2.9)
Platforms Linux x86_64 or ARM64 (glibc or musl) — pre-compiled binaries via PIE; macOS ARM64 — pre-compiled binary from GitHub Releases and Homebrew
Native extension ext-rabbit_rs as a Composer suggestion (version range declared in the driver's composer.json): composer install succeeds without it, and connections fail at resolution with a typed error until you pie install goopil/rabbit-rs-native
Delivery At-least-once: duplicates are permitted and measured (duplicates_total, messages_redelivered); silent loss after confirmed-path acceptance is a bug

Distribution channels

Package Channel Purpose
goopil/rabbit-rs-native PIE Native PHP extension (Linux and macOS binaries)
goopil/rabbit-rs-laravel Packagist Laravel queue driver (PHP source)
rabbit-rs Homebrew Native PHP extension (macOS binary, alternative to PIE)
ghcr.io/goopil/php-rabbit-rs Docker install images Copy the pre-compiled extension into your PHP image (Linux)

PIE selects the correct pre-compiled binary for your PHP version, architecture, operating system, libc, and thread-safety mode. Composer installs the Laravel bridge but does not install, verify, or modify system PHP: ext-rabbit_rs is a Composer suggestion, and the driver fails at connection resolution until the extension is loaded (PIE installs the binary).

  • Linux: PIE (Quick start above) or the Docker install images below.
  • macOS (Homebrew or manual binary): docs/reference.md.

Docker (Linux) — copy the pre-compiled extension into your PHP image, no build tools, no PIE step:

COPY --from=ghcr.io/goopil/php-rabbit-rs:latest-php8.5 /usr/local/ /usr/local/

Tags: latest-php8.2 through latest-php8.5, -alpine variants (libgcc bundled), and version-pinned tags (v0.3.14-php8.5-alpine), published on each release by install-images.yml. The images carry the NTS binary only: they COPY over php:N-cli bases, which are NTS. For ZTS (e.g. the official FrankenPHP images), install via PIE or download the Linux ZTS release assets directly (see Octane notes).

PECL, Debian/RPM/APK packages, Composer binary plugins, and full PHP images bundling the extension are explicitly out of scope for V1 — see Installation.

Stability

Stability is proven by scheduled kill-soaks, not by hope. The nightly soak runs a sustained publish/consume worker against a real RabbitMQ cluster and kills the broker repeatedly: the archived 60-minute run completed with 0 missing messages and 297/297 automatic reconnects (benchmarks/results/round-k-soak/), and every scenario in the chaos suite asserts the zero-loss invariant. Results are re-verified nightly in CI (soak workflow).

Delivery stays at-least-once under all of it — see Limitations for what that means in practice.

Limitations

Read before betting a pipeline on this.

  1. At-least-once means duplicates are possible — by contract, and measured. The broker redelivers any delivery that is not acknowledged (worker crash, channel loss, recovery), so consumers must treat an extra copy as normal: jobs must be idempotent. Duplicates are counted per run and become possible after any reconnect. The counters (duplicates_total, messages_redelivered) and idempotency guidance live in Reliability.
  2. The replay buffer is in-process memory, not durability. Unconfirmed publications survive connection recovery in a bounded in-process buffer (1024 publications / 64 MiB by default) and are replayed with the same message_id and original deadline. A PHP process crash empties it: the broker may never have received those messages, and nothing redelivers them to you. Broker redelivery after a crash covers the consume side (duplicates, not loss) — it is not publish durability. For cross-process durability you need an external outbox, which Rabbit RS does not include (What the replay buffer is not).

Documentation

Topic File
Getting started (native extension) docs/getting-started.md
Reference — installation, reliability, troubleshooting docs/reference.md
Getting started (Laravel driver) packages/laravel-queue/docs/getting-started.md
Reference — configuration, usage, topology, operations, recipes packages/laravel-queue/docs/reference.md
Benchmark harness and archived results benchmarks/README.md
Migration guides — from php-amqplib / from laravel-queue-rabbitmq docs/migration-from-php-amqplib.md · docs/migration-from-laravel-queue-rabbitmq.md
Laravel example app — job, Dockerfile, supervisor config examples/laravel/
Development guide docs/development.md
Security policy — reporting vulnerabilities SECURITY.md

Contributing

See CONTRIBUTING.md for the full guide, and docs/development.md for architecture, build system, test strategy, and common pitfalls. Quick reference:

cargo build -p rabbit-rs-php --features extension-tests   # build the extension
./scripts/check.sh                                        # quality gate: fmt + clippy + nextest + composer validate

License

MIT. See LICENSE.

About

Native Rust RabbitMQ transport for PHP and Laravel workers — at-least-once, auto-recovering, PIE-installable.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages