Search by

goopil / rabbit-rs-native

goopil

High-performance RabbitMQ transport for PHP and Laravel, powered by Rust

Package info

github.com/Goopil/php-rabbit-rs

Language:Rust

Type:php-ext

Ext name:ext-rabbit_rs

pkg:composer/goopil/rabbit-rs-native

Statistics

Installs: 122

Dependents: 0

Suggesters: 0

Stars: 3

Open Issues: 6

v0.3.14 2026-10-25 20:54 UTC

README

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

Rabbit RS is distributed via three 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 — including macOS Apple Silicon. Homebrew offers the same macOS binaries through the tap. 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).

macOS

PIE (Apple Silicon):

pie install goopil/rabbit-rs-native

Homebrew (Apple Silicon, alternative):

brew tap goopil/rabbit-rs
brew install rabbit-rs

Requires PHP 8.2, 8.3, 8.4, or 8.5 (Homebrew PHP for the tap).

Manual install (Apple Silicon):

On Apple Silicon (ARM64), download the pre-compiled binary from GitHub Releases and load it manually:

# Download the matching asset for your PHP version
unzip php_rabbit_rs-*_php8.4-arm64-darwin-bsdlibc-nts.zip
cp rabbit_rs.so $(php-config --extension-dir)/rabbit_rs.so
echo "extension=rabbit_rs" > $(php-config --ini-dir)/ext-rabbit_rs.ini
php -m | grep rabbit_rs

Alternatively, build from source:

git clone https://github.com/Goopil/php-rabbit-rs.git
cd php-rabbit-rs
./scripts/install.sh --release

Intel Macs (x86_64) are not distributed as pre-compiled binaries — build from source with ./scripts/install.sh --release.

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).

Not V1 distribution channels:

  • PECL
  • Debian/RPM/APK packages
  • Composer plugins that install binaries
  • Full PHP images bundling the extension

These are explicitly out of scope for V1. Use PIE or the Docker install images above in your Dockerfile — 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. Quick reference:

# Build the extension
cargo build -p rabbit-rs-php --features extension-tests

# Run tests
./scripts/test-laravel.sh          # Laravel Unit + Feature (no extension)
./scripts/test-extension.sh        # PHP extension (Pest + PHPT)
cargo test -p rabbit-rs-core       # Rust core

# Quality gate
./scripts/check.sh

For architecture, build system, test strategy, and common pitfalls, see docs/development.md.

License

MIT. See LICENSE.