You can connect RabbitMQ to NATS JetStream by running RabbitMQ as the message source, using Redpanda Connect as the bridge, and publishing processed messages into a JetStream stream. This tutorial walks through a local RabbitMQ setup, a Synadia Cloud NATS account with JetStream enabled, and a Redpanda Connect pipeline that consumes RabbitMQ messages, validates them, and writes them to NATS JetStream.
The example implements a one-way flow:
1RabbitMQ exchange and queue -> Redpanda Connect -> NATS JetStreamUse this pattern when you want RabbitMQ to handle queueing and routing while NATS JetStream stores and serves event streams for downstream processing.
In this tutorial, you will:

In this setup, RabbitMQ acts as the source where messages are produced. Redpanda Connect consumes messages from RabbitMQ, applies processing such as schema validation, and sends the processed messages to NATS JetStream as the sink.
RabbitMQ and NATS JetStream are both messaging technologies, but they are often used for different parts of an architecture.
Use this integration when you need to:
NATS JetStream provides message persistence, at-least-once delivery, and multiple consumption modes. RabbitMQ provides a rich broker model with queues, exchanges, routing keys, and plugin support. Redpanda Connect lets you build a pipeline that connects the two without writing a custom bridge service.
You will need the following:
The first step is to set up a NATS server with JetStream enabled. If you run your own NATS server, follow the official NATS setup documentation. To focus on the integration, this tutorial uses Synadia Cloud.

In Synadia Cloud, open the JetStream tab and create a stream. When creating a JetStream stream, specify a stream name, an optional description, and one or more subjects that the stream will store messages for.
For this tutorial, create a stream with:
analytics_streamanalytics.events.*Subjects in NATS are like topics or channels that messages are published to and subscribed from, such as analytics.events.login or user.notifications. NATS also supports wildcard subjects, which lets streams and subscriptions match hierarchical subject patterns.
Messages published to matching subjects such as analytics.events.login or analytics.events.purchase will be captured by the stream.

Run RabbitMQ with the management UI enabled:
docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.13-managementThis command pins rabbitmq:3.13-management; newer -management image tags (including the 4.x line) work the same way for the steps in this tutorial.
To verify that RabbitMQ is running, open http://localhost:15672/#/ in your browser and log in with:
guestguestNote on the
guestuser: By default, RabbitMQ’s built-inguestuser can only authenticate over a loopback (localhost) connection. Logging in to the management UI atlocalhost:15672works because that request comes from your machine. However, when Redpanda Connect runs in a separate container and connects throughhost.docker.internal, RabbitMQ sees a non-loopback connection and may rejectguestwith anACCESS_REFUSEDerror. If that happens, create a dedicated RabbitMQ user (management UI → Admin tab → Add a user, then grant it permissions on the/virtual host) and use those credentials inconnect.yaml, or start the RabbitMQ container with-e RABBITMQ_DEFAULT_USER=<user> -e RABBITMQ_DEFAULT_PASS=<password>to create a user that is not loopback-restricted.
With RabbitMQ running, create the queue and exchange that will handle the message flow.
RabbitMQ uses:
This tutorial uses the RabbitMQ management UI, but you can also create these resources through the RabbitMQ API or a client library.
In the RabbitMQ management UI:
analytics_events_queue.Durable.
Next:
analytics_events_exchange.topic.Durable.
Create a binding so messages published to the topic exchange are routed into the queue.
Use this routing key:
1analytics.events.#This binding routes any message with a RabbitMQ routing key that starts with analytics.events. to analytics_events_queue.
Note on wildcard semantics: RabbitMQ and NATS use different wildcard rules. In a RabbitMQ topic binding,
#matches zero or more words, soanalytics.events.#also matches deeper keys such asanalytics.events.user.login. The NATS stream subjectanalytics.events.*uses*, which matches exactly one token. The sample events in this tutorial use a single token afteranalytics.events.(login,purchase,logout), so both patterns line up. If you introduce routing keys with additional tokens, widen the NATS stream subject toanalytics.events.>(NATS>matches one or more trailing tokens) so JetStream still captures them.
To add the binding:
analytics_events_queue.analytics_events_exchange.analytics.events.# as the routing key.
Create a file named connect.yaml. This configuration tells Redpanda Connect to read from the RabbitMQ queue, validate messages against a JSON schema, and publish valid messages to NATS JetStream.
1input:2 label: analytics_queue3 amqp_0_9:4 urls:5 - 'amqp://guest:guest@host.docker.internal:5672/'6 queue: analytics_events_queue7pipeline:8 threads: 19 processors:10 - json_schema:11 schema_path: "file://path_to_schema.json"12 - catch:13 - log:14 level: ERROR15 message: "Schema validation failed due to: ${!error()}"16 - mapping: 'root = deleted()'17output:18 label: analytics_stream19 nats_jetstream:20 urls:21 - 'tls://connect.ngs.global'22 subject: '${! metadata("amqp_routing_key") }'23 headers:24 Content-Type: application/json25 auth:26 user_jwt: >-27 <NATS USER JWT>28 user_nkey_seed: <USER NKEY SEED>Replace the placeholder values before running the pipeline:
file://path_to_schema.json with the path to your JSON schema file.<NATS USER JWT> with the user JWT from your NATS credentials file.<USER NKEY SEED> with the user NKey seed from your NATS credentials file.Why the output subject is not a wildcard: A NATS publisher must publish to a concrete subject. Subjects that contain wildcard tokens (
*or>) are valid only for subscriptions and for stream or consumer subject filters — the NATS server rejects an attempt to publish to a wildcard subject. The configuration above sets the outputsubjectto${! metadata("amqp_routing_key") }, an interpolation that publishes each message to the subject matching its RabbitMQ routing key (for example,analytics.events.login). Those concrete subjects are all captured by theanalytics.events.*stream you created earlier. The metadata keyamqp_routing_keyis added by theamqp_0_9input; confirm the exact name against the input documentation for your Redpanda Connect version.If you prefer not to derive the subject from the routing key, publish every event to a single fixed subject instead — for example
subject: analytics.events.ingest. That subject still matches theanalytics.events.*stream, but all events then share one subject rather than mapping each event type to its own subject.
The input section is labeled analytics_queue. It uses the AMQP 0-9 protocol to connect to RabbitMQ at host.docker.internal:5672 with the default local credentials. It reads messages from analytics_events_queue.
The pipeline section runs with one thread and includes two processors:
json_schema validates incoming messages against the configured JSON schema.catch handles validation errors by logging the error and deleting invalid messages with a mapping operation.This step matters because it prevents malformed events from being written into JetStream.
The output section is labeled analytics_stream. It configures NATS JetStream as the output, sets a JSON content header, and authenticates with the NATS user credentials downloaded from Synadia Cloud. The subject field is the NATS subject each message is published to. It must resolve to a concrete subject (no wildcards); here it is derived from the message’s RabbitMQ routing key so each event type maps to its own subject under analytics.events..
Run Redpanda Connect from the directory where you saved connect.yaml:
docker run --rm -it -v $(pwd)/connect.yaml:/connect.yaml docker.redpanda.com/redpandadata/connect runWhen Redpanda Connect starts, it begins consuming messages from the RabbitMQ queue and publishing them to NATS JetStream. You should see logs similar to the following:
INFO Running main config from file found in a default path @service=benthos benthos_version=v4.31.0 path=connect.yamlINFO Listening for HTTP requests at: http://0.0.0.0:4195 @service=benthosINFO Launching a Redpanda Connect instance, use CTRL+C to close @service=benthosINFO Input type amqp_0_9 is now active @service=benthos label=analytics_queue path=root.inputINFO Output type nats_jetstream is now active @service=benthos label=analytics_stream path=root.outputUse the RabbitMQ management UI to publish sample analytics events.
analytics_events_exchange.analytics.events.login1{2 "user_id": 1234,3 "timestamp": "2024-06-01T10:30:00Z",4 "event_type": "login"5}analytics.events.purchase1{2 "user_id": 1234,3 "timestamp": "2024-06-01T11:15:00Z",4 "event_type": "purchase",5 "product_id": "ABC123",6 "amount": 99.997}analytics.events.logout1{2 "user_id": 1234,3 "timestamp": "2024-06-01T12:00:00Z",4 "event_type": "logout"5}Click Publish message for each event. RabbitMQ routes each message through analytics_events_exchange into analytics_events_queue, where Redpanda Connect consumes it.
To confirm that the messages were published to JetStream:

If the messages appear in the stream, the RabbitMQ to NATS JetStream integration is working.
Check the AMQP URL in connect.yaml:
1urls:2 - 'amqp://guest:guest@host.docker.internal:5672/'This address must be reachable from the Redpanda Connect container. host.docker.internal resolves to the host on Docker Desktop (macOS and Windows). On Linux, it is not defined by default — either add --add-host=host.docker.internal:host-gateway to the docker run command for Redpanda Connect, or update the URL to a RabbitMQ address that the container can reach (such as a shared Docker network or the host’s LAN address).
If the container reaches RabbitMQ but the connection is refused with an ACCESS_REFUSED authentication error, the cause is usually the guest user’s loopback restriction — see the note about the guest user in the RabbitMQ setup section above.
Verify that:
analytics_events_exchange.analytics_events_queue.analytics.events.#.analytics.events.login.Check the following:
subject resolves to a concrete subject (no * or > wildcards), and the stream’s subject filter (analytics.events.*) covers the subjects the output publishes to, such as analytics.events.login.The json_schema processor validates each message against your schema. If a message does not match the schema, the catch processor logs the validation error and deletes the invalid message from the pipeline before it reaches JetStream.
No. This tutorial shows a one-way pipeline from RabbitMQ to NATS JetStream. A reverse or bidirectional integration would require a separate configuration.
No. Synadia Cloud simplifies NATS and JetStream setup for this tutorial. You can also run and manage your own NATS server with JetStream enabled.
Redpanda Connect is the bridge. It consumes messages from RabbitMQ using AMQP 0-9, optionally processes or validates them, and writes the resulting messages to NATS JetStream.
Use RabbitMQ when you need exchange-based routing and queueing, and use NATS JetStream when you want persisted event streams for downstream consumers. Redpanda Connect lets you connect those roles in a pipeline.
Combining RabbitMQ routing with NATS JetStream persistence lets you support existing AMQP workflows while making selected events available through NATS. If you want to simplify the deployment and management of NATS JetStream, check out Synadia Cloud.
By combining RabbitMQ routing with NATS JetStream persistence and streaming, you can build messaging architectures that support existing AMQP workflows while making selected events available through NATS. If you are interested in simplifying the deployment and management of NATS JetStream, check out Synadia Cloud.
Want help from the NATS experts? Meet with our architects to get help tailored to your use case and environment.



News and content from across the community