PHP
Packagist
AdaptersLaravel · Symfony
A high-performance, agnostic queue standard that lets Laravel, Go, Python, Java, .NET and Node.js speak one strict JSON schema — no PHP serialize() lock-in, no broker glue.
Install the driver for your stack and start producing or consuming the same schema in minutes. Each core ships a framework adapter — no bridge services, no translation layer.
Packagist
AdaptersLaravel · Symfony
PyPI
AdaptersCelery · Django
pkg.go.dev
AdaptersRedis · RabbitMQ
npm
AdaptersBullMQ · NestJS
Maven Central
AdaptersSpring Boot
NuGet
AdaptersMassTransit
Here it is in Laravel — every SDK follows the same shape. The envelope on the wire is identical, so a Go, Python or .NET service consumes it natively.
Add the driver for your stack.
$ composer require babelqueue/laravel Publish by URN — no class is shared across languages.
BabelQueue::publish(
'urn:babel:orders:created',
['order_id' => 1042],
); Map the URN to a handler, in this or any other language.
// config/babelqueue.php
'urn:babel:orders:created'
=> OnOrderCreated::class, Pick any producer and consumer pair. BabelQueue emits the exact same strict JSON envelope, and the other language decodes it natively — only meta.lang reflects who produced it.
1use BabelQueue\Codec\EnvelopeCodec;23$env = EnvelopeCodec::make('urn:babel:orders:created', [4 'order_id' => 1042,5 'amount' => 99.90,6], 'orders');7$json = EnvelopeCodec::encode($env);
1use BabelQueue\Facades\BabelQueue;23BabelQueue::publish('urn:babel:orders:created', [4 'order_id' => 1042,5 'amount' => 99.90,6]);
1// OrderCreated implements PolyglotMessage2$bus->dispatch(new OrderCreated(1042));
1from babelqueue import EnvelopeCodec23env = EnvelopeCodec.make("urn:babel:orders:created", {4 "order_id": 1042,5 "amount": 99.90,6})
1bq = from_celery(celery_app, queue="orders")23bq.publish("urn:babel:orders:created", {"order_id": 1042})
1from babelqueue.django import publish23publish("urn:babel:orders:created", {"order_id": 1042})
1import "github.com/babelqueue/babelqueue-go"23env, _ := babelqueue.Make("urn:babel:orders:created", map[string]any{4 "order_id": 1042,5 "amount": 99.90,6})
1import { EnvelopeCodec } from '@babelqueue/core'23const env = EnvelopeCodec.make('urn:babel:orders:created', {4 order_id: 1042,5 amount: 99.90,6})
1import { publish } from '@babelqueue/bullmq'23await publish(queue, 'urn:babel:orders:created', { order_id: 1042 })
1constructor(private bq: BabelQueuePublisher) {}23this.bq.publish('urn:babel:orders:created', { order_id: 1042 })
1import com.babelqueue.EnvelopeCodec;23var env = EnvelopeCodec.make("urn:babel:orders:created", Map.of(4 "order_id", 1042,5 "amount", 99.906));
1babelQueue.publish("urn:babel:orders:created",2 Map.of("order_id", 1042L), "orders");
1using BabelQueue;23var env = EnvelopeCodec.Make("urn:babel:orders:created", new Dictionary<string, object?> {4 ["order_id"] = 1042,5 ["amount"] = 99.90,6});
1await babelQueue.PublishAsync("urn:babel:orders:created",2 new Dictionary<string, object?> { ["order_id"] = 1042L }, "orders");
{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "php",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "php",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "php",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "python",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "python",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "python",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "go",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "node",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "node",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "node",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "java",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "java",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "dotnet",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}{
"job": "urn:babel:orders:created",
"trace_id": "7b3f9c2a-e41d-4f88-9b2a-1c0d5e6f7a8b",
"data": {
"order_id": 1042,
"amount": 99.90
},
"meta": {
"id": "f1e2d3c4-b5a6-4789-90ab-cdef01234567",
"queue": "default",
"lang": "dotnet",
"schema_version": 1,
"created_at": 1749132727000
},
"attempts": 0
}1use BabelQueue\Codec\EnvelopeCodec;23$env = EnvelopeCodec::decode($body);4// EnvelopeCodec::urn($env) === 'urn:babel:orders:created'5$order = $env['data']['order_id'];
1// urn:babel:orders:created => OnOrderCreated::class2final class OnOrderCreated3{4 public function handle(array $data, array $meta)5 {6 // $data['order_id'] === 10427 }8}
1#[AsMessageHandler]2final class OnOrderCreated3{4 public function __invoke(OrderCreated $message): void5 {6 // $message->orderId === 10427 }8}
1env = EnvelopeCodec.decode(body)23# EnvelopeCodec.urn(env) == "urn:babel:orders:created"4order = env["data"]["order_id"]
1@bq.handler("urn:babel:orders:created")2def on_created(data, meta):3 order = data["order_id"]
1from babelqueue.django import get_app23@get_app().handler("urn:babel:orders:created")4def on_created(data, meta):5 order = data["order_id"]
1env, _ := babelqueue.Decode(body)23// env.Job == "urn:babel:orders:created"4order := env.Data["order_id"]
1const env = EnvelopeCodec.decode(body)23// EnvelopeCodec.urn(env) === 'urn:babel:orders:created'4const order = env.data.order_id
1import { processor } from '@babelqueue/bullmq'23new Worker('orders', processor({4 'urn:babel:orders:created': async (env) => {5 const order = env.data.order_id6 },7}))
1import { processor } from '@babelqueue/nestjs'23new Worker('orders', processor({4 'urn:babel:orders:created': async (env) => { /* env.data */ },5}))
1var env = EnvelopeCodec.decode(body);23// EnvelopeCodec.urn(env) → "urn:babel:orders:created"4var order = env.data().get("order_id");
1@RabbitListener(queues = "orders")2void onMessage(Envelope env) {3 var order = env.data().get("order_id");4}
1var env = EnvelopeCodec.Decode(body);23// EnvelopeCodec.Urn(env) → "urn:babel:orders:created"4var order = env.Data["order_id"];
1public Task Consume(ConsumeContext<Envelope> ctx)2{3 var order = ctx.Message.Data["order_id"];4 return Task.CompletedTask;5}
The opinionated defaults you actually want in production — typed, traceable, and broker-agnostic from day one.
Strongly-typed, pure JSON envelopes replace fragile PHP serialize() — readable, portable and validated against a strict schema.
Every message carries a built-in trace_id, so a failure three services deep is one query away — across any language boundary.
First-class support for Redis and RabbitMQ. Swap backends with a config line — your producers and consumers never change.
No sidecar, no proxy, no broker plugin. BabelQueue talks straight to native drivers — adding nothing between your app and the queue.
The other paths to cross-language messaging mean new infrastructure or losing your framework's ergonomics. BabelQueue changes only the serialization.
| BabelQueue | PHP serialize() | Kafka / gRPC rewrite | Hand-rolled bridge | |
|---|---|---|---|---|
| Keep your Redis / RabbitMQ broker | ✓ | ✓ | ✗ | ✓ |
| No new infrastructure or sidecar | ✓ | ✓ | ✗ | ~ |
| Consumed natively in any language | ✓ | ✗ | ✓ | ✓ |
| Drop-in — reuse your framework's worker | ✓ | ✓ | ✗ | ✗ |
| Built-in cross-service trace_id | ✓ | ✗ | ~ | ✗ |
| Zero heavy dependencies | ✓ | ✓ | ✗ | ~ |
The things teams ask before adopting BabelQueue. Still curious? The full standard is in the wire contract.
No. BabelQueue runs on the Redis or RabbitMQ you already operate — it changes the serialization, not the transport. There is no new broker, sidecar or proxy to deploy.
No. Standard framework jobs and workers stay exactly as they are. Only connections you opt into as polyglot use the canonical envelope, so adoption is incremental.
All six SDKs are released at 1.0: PHP (Laravel & Symfony), Python (Celery & Django), Go (Redis & RabbitMQ transports), Node.js (BullMQ & NestJS), Java (Spring Boot) and .NET (MassTransit) — each a framework-agnostic core plus a framework adapter.
Yes. The envelope is frozen at schema_version 1: fields are never added, renamed, removed or retyped without a deliberate version bump. A v1 producer stays readable by every v1 consumer, in any language, indefinitely.
By a URN (urn:babel:<context>:<event>) carried in the envelope, never a class name — so a Go or Python consumer routes on a stable string without sharing any type with the producer.
Negligible. The codec adds well under 2% over the plain-JSON serialization a publisher already pays, measured against a conservative broker round-trip — and it talks straight to native drivers, with nothing in between.
Every message carries a trace_id, generated by the first producer and preserved unchanged across every hop and language — so an end-to-end trace is one query away, no manual plumbing.
Free, open-source, and production-ready. Drop in a driver and your polyglot queue just works.