--- title: "Broker transports" description: "Run BabelQueue over any Symfony Messenger transport — built-in (AMQP, Redis) or third-party (Kafka, AMQP 1.0) — with the babelqueue.messenger.serializer. Interop is body-authoritative, so no broker-specific BabelQueue transport is needed." source: https://babelqueue.com/docs/symfony/1.x/broker-transports/ updated: 2026-06-14T00:00:00.000Z --- # Broker transports The BabelQueue adapter is a Messenger **serializer**, not a transport. It encodes and decodes the [canonical envelope](/docs/spec/1.x/envelope/) on whatever Messenger transport you configure — so **Symfony interoperates over any broker Messenger can reach**, and there is no broker-specific "BabelQueue transport" to install. Point a transport at the serializer and you are done: ```yaml # config/packages/messenger.yaml framework: messenger: transports: babel: dsn: '%env(MESSENGER_TRANSPORT_DSN)%' serializer: 'babelqueue.messenger.serializer' ``` ## Built-in transports (RabbitMQ, Redis) Messenger ships first-party transports for **AMQP** (RabbitMQ — [§2](/docs/spec/1.x/broker-bindings/)) and **Redis** ([§1](/docs/spec/1.x/broker-bindings/)). Set the DSN and the serializer; a Go / Python / Laravel / … consumer on the same broker reads the byte-identical envelope: ```dotenv # RabbitMQ MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/orders # …or Redis MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages ``` These are the GA path for Symfony; see the [broker setup recipes](/docs/spec/1.x/broker-recipes/) for the cross-language pairings. ## Beyond the built-ins (Kafka, Pulsar, Artemis/AMQP 1.0) Messenger has **no first-party transport** for Kafka ([§6](/docs/spec/1.x/broker-bindings/)), Pulsar ([§5](/docs/spec/1.x/broker-bindings/)) or Artemis over AMQP 1.0 ([§7](/docs/spec/1.x/broker-bindings/)). You do **not** need a BabelQueue-specific transport for them — use a **third-party Messenger transport** for that broker and wire the same `babelqueue.messenger.serializer` onto it. The serializer puts the canonical envelope in the message **body**, so the wire format is identical regardless of which transport carries it. ```yaml framework: messenger: transports: babel-kafka: dsn: '%env(KAFKA_TRANSPORT_DSN)%' # from a community Kafka Messenger transport serializer: 'babelqueue.messenger.serializer' ``` > **Interop is body-authoritative.** A cross-language consumer routes on the body's `job` > URN, which is always present — so a Symfony-produced message is consumed correctly on any > of these brokers even when the transport doesn't reproduce the binding's *native* property > projection (AMQP `type`, Pulsar/Kafka `bq-job` header, …). The serializer also emits the > cross-broker `bq-*` headers (`bq-job`, `bq-trace-id`, `bq-message-id`, `bq-schema-version`, > `bq-source-lang`, `bq-attempts`); a transport that maps serializer headers onto native > broker headers (e.g. a Kafka Messenger transport → Kafka record headers) carries them > through, so consumers can also route without decoding the body. ## When you want the native projection If you need the **exact native projection** of a binding (so non-PHP consumers route on the broker-native field — AMQP `type`, SQS `MessageAttributes`, the Pulsar/Kafka `bq-` headers, the Artemis STOMP framing), reach for the framework-less [`babelqueue/php-sdk`](/docs/php-sdk/1.x/transports/) transports directly instead of going through Messenger: | Broker | Native produce / consume on `php-sdk` | | :--- | :--- | | Apache Kafka (§6) | `KafkaTransport` (produce) · `KafkaConsumer` + retry topics (consume) | | Apache Pulsar (§5) | `PulsarTransport` (produce) · `PulsarConsumer` (consume) | | Apache Artemis (§7) | `StompTransport` (produce); Laravel ships the `babelqueue-artemis` consume driver | | Amazon SQS (§3) | `SqsTransport` | These emit the binding's native `bq-`/property projection verbatim. The envelope is the same `schema_version: 1` either way — Messenger-serializer or framework-less transport is purely a wiring choice.