--- title: "Broker setup recipes" description: "Quick-start recipes for pointing each BabelQueue SDK at a broker — worked examples for Redis and RabbitMQ, plus where to find the other five (SQS, Azure SB, Pulsar, Kafka, Artemis). The exact connection, runtime, transport or DSN per language, all producing and consuming the one canonical envelope." source: https://babelqueue.com/docs/spec/1.x/broker-recipes/ updated: 2026-06-15T00:00:00.000Z --- # Broker setup recipes A copy-paste recipe per SDK for the two most common brokers — **Redis** and **RabbitMQ** — so a message produced in one language is consumed in another over the broker you already run. Every recipe emits and reads the exact [canonical envelope](/docs/spec/1.x/envelope/) (`schema_version: 1`); only the wiring differs. The body is identical everywhere, so any pairing interoperates — see the [broker bindings](/docs/spec/1.x/broker-bindings/) for how each broker carries it natively. > **Seven brokers are GA — these recipes cover two of them.** Redis and RabbitMQ are > the worked examples below; the same shape extends to **Amazon SQS**, **Azure Service > Bus**, **Apache Pulsar**, **Apache Kafka** and **Apache ActiveMQ/Artemis**, all GA and > conformance-locked. For those five, swap in the matching transport/extra — Go > `…/sqs · …/pulsar · …/kafka · …/artemis · …/azureservicebus`, Python `[sqs] [pulsar] > [kafka] [artemis]` (+ Azure SB), Node `@babelqueue/sqs · …/pulsar · …/kafka · …/artemis > · …/azure-service-bus`, Java `babelqueue-sqs/-pulsar/-kafka/-artemis/-azureservicebus`, > .NET `BabelQueue.Sqs/.Pulsar/.Kafka/.Artemis/.AzureServiceBus`, and PHP `php-sdk` > `SqsTransport` / `KafkaTransport`+`KafkaConsumer` / `PulsarTransport`+`PulsarConsumer` / > `StompTransport` (Artemis) plus the Laravel `babelqueue-sqs` and `babelqueue-artemis` > drivers. The one documented gap is **PHP × Azure Service Bus**. The per-broker > projection is in the [broker bindings](/docs/spec/1.x/broker-bindings/); the keys are in > the [configuration reference](/docs/spec/1.x/broker-bindings/). > **Runtime vs core-only.** The shapes differ by language: a *runtime* SDK (Laravel, > Symfony, Python, Go's `App`, Node adapters) gives you `publish`/worker out of the box, > while a *core-only* SDK (.NET, Java core) is a codec — you move the bytes with your own > broker client, or a dedicated transport where one ships (e.g. `BabelQueue.Redis`, > `com.babelqueue:babelqueue-redis`). Where a language has no first-party RabbitMQ > transport on the core, the recipe uses its framework adapter (MassTransit, Spring AMQP), > which is the supported path. All recipes use the same queue (`orders`) and URN (`urn:babel:orders:created`) so you can mix any producer with any consumer. ## PHP / Laravel Laravel plugs in as a custom queue connection. Pick the driver per broker in `config/queue.php`: ```php // config/queue.php — Redis 'connections' => [ 'babelqueue' => [ 'driver' => 'babelqueue-redis', 'connection' => 'default', 'queue' => env('BABELQUEUE_QUEUE', 'orders'), 'retry_after' => 90, ], ], ``` ```php // config/queue.php — RabbitMQ 'connections' => [ 'babelqueue' => [ 'driver' => 'babelqueue-rabbitmq', 'host' => env('RABBITMQ_HOST', '127.0.0.1'), 'port' => env('RABBITMQ_PORT', 5672), 'queue' => env('BABELQUEUE_QUEUE', 'orders'), ], ], ``` Publish with the facade and run the standard worker against the connection: ```php use BabelQueue\Facades\BabelQueue; BabelQueue::publish('urn:babel:orders:created', ['order_id' => 1042]); ``` ```bash php artisan queue:work babelqueue ``` URN→handler mapping and the dead-letter policy live in `config/babelqueue.php` — see [Laravel configuration](/docs/laravel/1.x/configuration/). ## PHP / Symfony Symfony Messenger keeps its own transport DSN — `redis://` or `amqp://` — and you swap in the BabelQueue serializer so the wire format is the canonical envelope: ```yaml # config/packages/messenger.yaml framework: messenger: transports: babel: dsn: '%env(MESSENGER_TRANSPORT_DSN)%' # redis://localhost:6379/messages # or amqp://guest:guest@localhost:5672/%2f/messages serializer: 'babelqueue.messenger.serializer' routing: 'App\Message\OrderCreated': babel ``` Map inbound URNs back to message classes in `config/packages/babelqueue.yaml`, then dispatch and consume the Messenger way (`messenger:consume babel`). See [Symfony configuration](/docs/symfony/1.x/configuration/). ## PHP (framework-less core) The `babelqueue/php-sdk` core is a codec; its optional reference transports move the bytes. `RedisTransport` (over `predis/predis`) and `AmqpTransport` (over `php-amqplib`) both publish the encoded envelope: ```php use BabelQueue\Codec\EnvelopeCodec; use BabelQueue\Transport\RedisTransport; $transport = new RedisTransport(new Predis\Client('redis://localhost:6379')); $env = EnvelopeCodec::make('urn:babel:orders:created', ['order_id' => 1042], 'orders'); $transport->publish(EnvelopeCodec::encode($env), 'orders'); ``` Swap `RedisTransport` for `AmqpTransport` to publish to RabbitMQ — see [PHP transports](/docs/php-sdk/1.x/transports/). ## Python The Python runtime chooses its transport from the broker URL scheme — `redis://` or `amqp://`. Install the matching extra: ```python # pip install "babelqueue[redis]" → Redis # pip install "babelqueue[amqp]" → RabbitMQ (via pika) from babelqueue import BabelQueue app = BabelQueue("redis://localhost:6379/0", queue="orders") # app = BabelQueue("amqp://guest:guest@localhost:5672/", queue="orders") app.publish("urn:babel:orders:created", {"order_id": 1042}) ``` Register handlers and run the worker as in [Python configuration](/docs/babelqueue-python/1.x/configuration/). ## Go The Go core is a codec; the optional zero-dependency `App` runtime plus a per-broker transport module gives you publish/consume. Install the module you need: ```go // go get github.com/babelqueue/babelqueue-go/redis → Redis // go get github.com/babelqueue/babelqueue-go/amqp → RabbitMQ import ( babelqueue "github.com/babelqueue/babelqueue-go" "github.com/babelqueue/babelqueue-go/redis" ) tr, err := redis.New("redis://localhost:6379/0") // amqp.New("amqp://guest:guest@localhost:5672/") if err != nil { return err } defer tr.Close() app := babelqueue.NewApp(tr, babelqueue.WithDefaultQueue("orders")) app.Handle("urn:babel:orders:created", func(ctx context.Context, env babelqueue.Envelope) error { return nil // env.Data, env.TraceID }) app.Publish(ctx, "urn:babel:orders:created", map[string]any{"order_id": 1042}) return app.Consume(ctx) // blocks ``` The Redis transport runs the reliable-queue pattern; AMQP uses durable queues with manual ack. See [Runtime & transports](/docs/babelqueue-go/1.x/runtime-and-transports/). ## Node.js Beyond `@babelqueue/core`, thin transport packages wire it to each broker — you bring the client: ```ts // npm install @babelqueue/redis ioredis → Redis import Redis from "ioredis"; import { RedisPublisher, RedisConsumer } from "@babelqueue/redis"; const client = new Redis("redis://localhost:6379/0"); await RedisPublisher.create(client, "orders") .publish("urn:babel:orders:created", { order_id: 1042 }); const consumer = new RedisConsumer(client, "orders", { "urn:babel:orders:created": (env) => console.log(env.data.order_id, env.trace_id), }, { maxTries: 3 }); await consumer.run(() => true); ``` ```ts // npm install @babelqueue/rabbitmq amqplib → RabbitMQ import amqp from "amqplib"; import { RabbitMQPublisher } from "@babelqueue/rabbitmq"; const channel = await (await amqp.connect("amqp://guest:guest@localhost:5672/")).createChannel(); await channel.assertQueue("orders", { durable: true }); await RabbitMQPublisher.create(channel, "orders") .publish("urn:babel:orders:created", { order_id: 1042 }); ``` For a BullMQ/NestJS stack on Redis, use `@babelqueue/bullmq` / `@babelqueue/nestjs` — see [Adapters & transports](/docs/babelqueue-node/1.x/adapters/). ## Java The Java core is a codec. For **Redis** it ships a first-party transport, `com.babelqueue:babelqueue-redis` (built on Lettuce): ```java import com.babelqueue.redis.RedisPublisher; import io.lettuce.core.RedisClient; import io.lettuce.core.api.sync.RedisCommands; import java.util.Map; RedisClient client = RedisClient.create("redis://localhost:6379"); RedisCommands redis = client.connect().sync(); RedisPublisher.create(redis, "orders") .publish("urn:babel:orders:created", Map.of("order_id", 1042L)); ``` For **RabbitMQ**, use the Spring Boot adapter `com.babelqueue:babelqueue-spring`: its auto-configured `MessageConverter` wires the canonical envelope into `RabbitTemplate` (producing) and `@RabbitListener` (consuming): ```java @Service class Orders { private final BabelQueuePublisher babelQueue; Orders(BabelQueuePublisher babelQueue) { this.babelQueue = babelQueue; } void create() { babelQueue.publish("urn:babel:orders:created", Map.of("order_id", 1042L), "orders"); } } ``` See the [Redis transport](/docs/babelqueue-java/1.x/redis/) and [Spring Boot adapter](/docs/babelqueue-java/1.x/spring/). ## .NET The .NET core is a codec. For **Redis** it ships `BabelQueue.Redis` (built on StackExchange.Redis): ```csharp using BabelQueue.Redis; using StackExchange.Redis; var redis = await ConnectionMultiplexer.ConnectAsync("localhost:6379"); var db = redis.GetDatabase(); await new RedisPublisher(db, "orders") .PublishAsync("urn:babel:orders:created", new Dictionary { ["order_id"] = 1042 }); ``` For **RabbitMQ**, use the MassTransit adapter `BabelQueue.MassTransit`: register its `System.Text.Json` envelope converter so MassTransit's RabbitMQ transport carries the canonical envelope. (You can also encode with `EnvelopeCodec.Encode(...)` and publish with your own `RabbitMQ.Client` channel.) See the [Redis transport](/docs/babelqueue-dotnet/1.x/redis/) and [MassTransit adapter](/docs/babelqueue-dotnet/1.x/masstransit/). ## Cross-language sanity check Because every recipe writes the same envelope to the same `orders` queue, you can mix producers and consumers freely — e.g. a Python `redis://` producer and a Go `…/redis` consumer, or a Laravel `babelqueue-rabbitmq` producer and a Node `@babelqueue/rabbitmq` consumer. For a runnable end-to-end demo, see [Cross-language: Python → Go over Redis](/docs/examples/1.x/cross-language-redis/). Continue to [Dead-letter & tracing](/docs/spec/1.x/dead-letter-and-tracing/).