RabbitMQ
RabbitMQ is an open source message broker that routes messages through exchanges and queues. Learn how it works, when to use it and how it feeds data pipelines.
Overview
RabbitMQ is a message broker. It sits between programs that produce messages and programs that consume them, and it decides where each message goes. A producer sends a message to an exchange. The exchange applies routing rules and places copies of the message into one or more queues. Consumers read from those queues and acknowledge each message when the work is done. This indirection lets systems stay loosely coupled, absorb bursts of traffic and retry failed work.
The broker is best known for task queues and application-level messaging. It supports several delivery patterns, including work queues, publish-subscribe, topic routing and request-reply. It speaks AMQP 0-9-1 natively and supports other protocols through plugins. For teams that move rows, events and files between services before a table ever reaches a database or a model, RabbitMQ is a common and well understood building block. This article explains how it works, how it compares with log-based systems such as Apache Kafka and lightweight systems such as NATS, and how it fits into pipelines that feed tabular foundation models.
What it is
RabbitMQ is an open source message broker written in Erlang and built on the Open Telecom Platform. Erlang gives it lightweight processes, supervision trees and good behavior under many concurrent connections. The broker keeps state about exchanges, queues, bindings, users and permissions, and it exposes that state through a management interface and a command line tool.
The core roles
- A producer is any program that publishes a message.
- An exchange receives messages from producers and routes them.
- A queue stores messages until a consumer takes them.
- A binding links an exchange to a queue with a routing rule.
- A consumer reads messages from a queue and acknowledges them.
- A virtual host is a namespace that isolates a set of exchanges, queues and permissions.
An everyday analogy
Think of a large post office. A sender drops a parcel at the front counter. The clerk reads the label and decides which sorting bin it belongs in. Each bin is emptied by a different delivery person. The clerk is the exchange, the bins are the queues, the label is the routing key and the delivery people are the consumers. The sender never needs to know who will deliver the parcel. If a delivery person is slow, parcels simply wait in the bin.
Message structure
A message has a body, which is a plain byte array, and a set of properties. The properties include a content type, headers, a delivery mode that marks the message as persistent or transient, a correlation identifier, a reply-to address and an optional expiry. The broker does not look inside the body. This is important for data work: the body might be JSON, Avro, Protobuf or a compressed batch of rows, and the broker treats all of them the same way.
Where it came from
RabbitMQ was created in the mid 2000s as an implementation of the Advanced Message Queuing Protocol. AMQP was designed so that banks and other large organizations could exchange messages across vendors without lock-in to a proprietary product. The early broker was written in Erlang because the language was built for telephone switches, which also need reliability and many concurrent connections.
Over the years the project was acquired by larger infrastructure companies and has been maintained as open source under a permissive license. The 3.x series added features such as mirrored queues, federation, shovel and a rich plugin system. Later releases introduced quorum queues, which use a consensus protocol for replication, and streams, which provide an append-only log with non-destructive reads. The 4.x series continued this direction and gave more weight to AMQP 1.0 support in the core.
Timeline in general terms
| Period | Development |
|---|---|
| Mid 2000s | First releases, AMQP 0-9-1 as the main protocol |
| 2010s | Plugins for STOMP, MQTT, HTTP and web protocols; management UI; clustering |
| Late 2010s | Quorum queues introduced as a safer replicated queue type |
| Early 2020s | Streams added for log-style workloads and replay |
| Recent releases | Native AMQP 1.0, improved defaults, classic mirrored queues deprecated |
Exact version numbers and dates are best checked against the official release notes of the version you plan to run.
How it works
This section walks through a message from publication to acknowledgement.
Step 1: connect and open a channel
A client opens a TCP connection to the broker and then opens one or more channels on top of it. A channel is a lightweight virtual connection. Applications use channels so that they do not pay the cost of a new TCP connection for every thread or task. Think of the connection as a road and the channels as lanes.
Step 2: declare topology
Before sending or receiving, the application declares the exchanges and queues it needs, and the bindings between them. Declarations are idempotent. If the object already exists with the same settings, nothing changes. If it exists with different settings, the broker raises an error. Many teams declare topology in code at start-up, and some manage it with definitions files or infrastructure tools.
Step 3: publish to an exchange
The producer publishes a message with a routing key. It does not name a queue directly in most designs. The exchange type decides how the routing key is used.
| Exchange type | Routing rule | Typical use |
|---|---|---|
| Direct | Exact match on routing key | Send a job to a specific worker group |
| Fanout | Copy to every bound queue | Broadcast an event to many services |
| Topic | Pattern match with wildcards | Route by category such as sensor.eu.temperature |
| Headers | Match on message headers | Route by several attributes at once |
| Default | Routes to the queue named by the key | Quick point-to-point sends |
Step 4: the queue stores the message
A queue holds messages in order. Queue types matter a great deal.
- Classic queues are the original type. They are fast and simple. Replicated mirroring of classic queues is deprecated in recent releases.
- Quorum queues replicate across nodes using a Raft-based consensus protocol. They favor data safety and are the recommended choice for durable work.
- Streams are append-only logs. Consumers read by offset, and messages stay until a retention rule removes them.
A durable queue survives a broker restart. A persistent message is written to disk. You need both to keep data across restarts.
Step 5: deliver to a consumer
The broker pushes messages to consumers that have subscribed, up to a limit called the prefetch count. The prefetch count controls how many unacknowledged messages a consumer may hold at once. A low value spreads work evenly among workers. A high value raises throughput but can let one slow worker hoard messages.
Step 6: acknowledge, reject or requeue
When a consumer finishes, it sends an acknowledgement and the broker removes the message. If the consumer fails, the connection drops and the broker requeues the unacknowledged messages for another consumer. A consumer can also reject a message explicitly. A rejected message can be requeued or sent to a dead letter exchange.
Step 7: publisher confirms
On the producer side, publisher confirms let the broker tell the publisher that a message has been taken in safely. Without confirms, a producer cannot know whether the broker received the message. With confirms and persistent messages on a quorum queue, the producer gets a strong signal that the message will not be lost.
Reliability features at a glance
- Acknowledgements protect against consumer failure.
- Publisher confirms protect against producer to broker loss.
- Durable queues and persistent messages protect against restarts.
- Quorum queues protect against node loss.
- Dead letter exchanges catch poison messages and expired messages.
- Time to live settings drop stale messages.
- Delivery limits stop endless redelivery loops.
Key concepts and terms
| Term | Meaning |
|---|---|
| AMQP | Advanced Message Queuing Protocol, the wire protocol RabbitMQ was built around |
| Exchange | The routing component that receives published messages |
| Queue | An ordered buffer that holds messages for consumers |
| Binding | A rule that connects an exchange to a queue |
| Routing key | A string on the message used by the exchange to choose queues |
| Virtual host | A logical namespace with its own exchanges, queues and permissions |
| Prefetch | The cap on unacknowledged messages per consumer or channel |
| Acknowledgement | A consumer signal that a message was handled |
| Dead letter exchange | An exchange that receives rejected or expired messages |
| Quorum queue | A replicated queue type that uses a consensus protocol |
| Stream | An append-only log type with offset-based reading |
| Shovel | A plugin that moves messages between brokers |
| Federation | A plugin that links exchanges or queues across brokers |
| Publisher confirm | A broker signal that a published message was accepted |
| Delivery mode | Transient or persistent flag on a message |
| Competing consumers | Several workers reading from one queue to share work |
A worked example
Suppose a service receives uploaded CSV files with customer records. Each file must be validated, split into chunks, scored by a model and written to a database. The team uses RabbitMQ to decouple these steps.
Topology
- An exchange named
ingestof type topic. - A queue named
validatebound with the keyfile.uploaded. - A queue named
scorebound with the keychunk.ready. - A dead letter exchange named
ingest.deadwith a queue namedfailed.
Declaring topology in Python
The example uses the common pika client. The host name is a placeholder.
import json
import pika
params = pika.ConnectionParameters(host="broker.example.internal")
conn = pika.BlockingConnection(params)
ch = conn.channel()
ch.exchange_declare("ingest", exchange_type="topic", durable=True)
ch.exchange_declare("ingest.dead", exchange_type="fanout", durable=True)
ch.queue_declare("failed", durable=True)
ch.queue_bind("failed", "ingest.dead")
args = {
"x-queue-type": "quorum",
"x-dead-letter-exchange": "ingest.dead",
"x-delivery-limit": 5,
}
for name, key in [("validate", "file.uploaded"), ("score", "chunk.ready")]:
ch.queue_declare(name, durable=True, arguments=args)
ch.queue_bind(name, "ingest", routing_key=key)
Publishing with confirms
ch.confirm_delivery()
body = json.dumps({"file_id": "f-001", "path": "s3://bucket.example.internal/f-001.csv"})
ch.basic_publish(
exchange="ingest",
routing_key="file.uploaded",
body=body.encode(),
properties=pika.BasicProperties(
delivery_mode=2,
content_type="application/json",
message_id="f-001",
),
)
A consumer that validates and forwards
def on_message(channel, method, props, body):
job = json.loads(body)
try:
chunks = validate_and_split(job["path"])
for i, chunk_path in enumerate(chunks):
channel.basic_publish(
"ingest", "chunk.ready",
json.dumps({"file_id": job["file_id"], "chunk": i, "path": chunk_path}).encode(),
pika.BasicProperties(delivery_mode=2, message_id=f"{job['file_id']}-{i}"),
)
channel.basic_ack(method.delivery_tag)
except ValueError:
channel.basic_reject(method.delivery_tag, requeue=False)
ch.basic_qos(prefetch_count=4)
ch.basic_consume("validate", on_message)
ch.start_consuming()
What happens
- The upload service publishes
file.uploaded. - The exchange routes it to the
validatequeue. - A worker validates the file, publishes several
chunk.readymessages and acknowledges the original. - Scoring workers pull chunks from
scorein parallel. - If a file is malformed, the worker rejects it without requeue and the message lands in
failedfor inspection. - If a worker crashes mid-job, the unacknowledged message returns to the queue and another worker takes it.
Numeric walk-through of prefetch
Imagine one queue with 100 chunks and 4 workers. Each chunk takes 2 seconds on average but a few take 20 seconds. With a prefetch of 25, the broker might hand 25 chunks to each worker at once. A worker that draws several slow chunks becomes the bottleneck while others sit idle. With a prefetch of 1 or 2, a worker only gets new work when it finishes, so the load balances itself. The cost is more network round trips. A middle value such as 4 is often a good start, then measure.
Idempotency
Because redelivery can happen, the scoring step should be idempotent. Using message_id as a key in a database table with a unique constraint means a repeated message cannot create duplicate rows. This is the standard way to get effectively once processing on top of at least once delivery.
Strengths and limitations
Strengths
- Flexible routing with direct, topic, fanout and headers exchanges.
- Mature client libraries in most languages.
- Per-message acknowledgements and fine control over redelivery.
- Priority queues, time to live, dead lettering and delayed delivery patterns.
- A readable management interface and good metrics for monitoring.
- Several protocols through plugins, including MQTT and STOMP.
- Quorum queues give strong durability for important work.
- Works well for task distribution and request-reply patterns.
Limitations
- A classic queue is not a log. Once a message is consumed and acknowledged, it is gone. Replay needs streams or a separate store.
- Throughput per queue is limited by the single queue process model, so very high volumes need many queues or streams.
- Long queues that grow into millions of messages put pressure on memory and disk.
- Cluster networks that partition need careful configuration of partition handling.
- Ordering is guaranteed within a queue for one consumer, but competing consumers and requeues can change processing order.
- Operating a cluster needs attention to disk space, memory alarms and file descriptor limits.
When it fits and when it does not
| Situation | Fit |
|---|---|
| Background jobs and task queues | Strong |
| Routing events by pattern to many services | Strong |
| Request-reply between services | Good |
| Replayable event history with many independent readers | Better with a log such as Apache Kafka or RabbitMQ streams |
| Ultra low latency, simple subjects | Consider NATS |
| Constrained devices and sensors | Consider MQTT at the edge |
How it compares with alternatives
| Feature | RabbitMQ | Apache Kafka | NATS | Redis streams or lists |
|---|---|---|---|---|
| Core model | Broker with exchanges and queues | Partitioned replicated log | Subject-based messaging with optional persistence | Data structures used as queues |
| Message retention | Until acknowledged, or by stream policy | By time or size policy | By stream policy in JetStream | By trimming rules |
| Replay | Streams only | Native | JetStream | Streams |
| Routing | Rich, server side | By topic and partition key | Subject wildcards | Manual |
| Typical scale pattern | Many queues, moderate volume each | Very high throughput per topic | Very high message rates with small payloads | Moderate |
| Consumer model | Push with prefetch | Pull by offset | Push or pull | Pull |
| Best for | Task queues, workflow, routing | Event streaming and analytics | Service communication, low latency | Simple queues near a cache |
Related ideas include event-driven architecture and event sourcing. RabbitMQ can carry events in either style, but it is not an event store in the classic sense.
Choosing in practice
Ask three questions. First, do consumers need to re-read old messages? If yes, favor a log. Second, is routing logic complex, with many patterns and per-message rules? If yes, RabbitMQ shines. Third, how many messages per second and how large? For extreme volumes, a partitioned log or a very light broker may suit better. Many organizations use more than one tool, for example RabbitMQ for commands and jobs and a log for analytic events.
Role in tabular foundation models
RabbitMQ is not a model and it does not understand tables. Its role is to move, buffer and route the data that tabular foundation models consume or produce. This section stays concrete about where it helps and avoids claiming any particular product integration.
Why messaging matters to table models
A tabular foundation model learns from raw tables with rows and columns, mixed numeric, categorical, text and date types, missing values and sometimes no useful column names. Such a model is often served with in-context learning, where a set of labeled example rows is given together with the rows to predict. That makes the serving path data heavy. Rows must arrive in batches, be validated, be packed into a context, scored and returned. A broker is a natural fit for that path. See the architecture overview for how such models consume a table.
Concrete uses
- Ingest buffering. Source systems publish row batches to a queue. Scoring workers pull batches at their own speed, so a burst of uploads does not overwhelm the model server. This is the classic load leveling role.
- Job orchestration. A request to predict, impute or flag anomalies becomes a message. Workers pick up the job, call the model and publish the result to a reply queue or a results exchange.
- Fan-out of results. A fanout or topic exchange can send the same prediction event to a database writer, an alerting service and an audit log at once.
- Retry and isolation. Bad files, such as tables with an unexpected schema, go to a dead letter queue instead of blocking the pipeline. Engineers can inspect them without stopping good traffic.
- Backpressure. A bounded queue and a small prefetch protect a GPU-backed model server from overload. Producers see confirms slow down or use flow control.
- Context assembly. In an in-context learning setup, one service can collect a reference sample of labeled rows while another collects query rows. A routing key tied to a dataset identifier ensures both land with the same worker, so the context and the query meet in one place.
Task types that map well
| Task | How messaging helps |
|---|---|
| Classification and regression on batches | Queue of row chunks, worker pool, result exchange |
| Imputation of missing values | Jobs per table or column group; results written back by a separate consumer. See imputation networks and masked cell modeling for the modeling side |
| Anomaly detection on streams of rows | Topic exchange by source; workers score and publish only flagged rows. See anomaly detection |
| Sector or semantic classification of columns | A job per uploaded table; workers classify column semantics and publish tags to a catalog service |
| Continual learning | A queue of newly labeled rows feeds a periodic update job, with versioned model identifiers in message headers |
| Synthetic data creation | Generation jobs fan out across workers. See synthetic data generation |
Design notes for model pipelines
- Put the model version, schema version and dataset identifier in message headers. Consumers can then reject or route messages that do not match.
- Keep message bodies small. Send a pointer to an object store for large tables, plus a checksum, instead of a huge body. Large messages slow the broker and fill memory.
- Use idempotent writes keyed by message identifier so that redelivery never double counts rows.
- Treat the queue as transport, not as the system of record. Persist inputs and outputs in a database or a lake.
- Sensitive columns should be protected before they enter shared queues. See data tokenization and format-preserving encryption.
- Watch queue depth and age as health signals. A growing oldest-message age is an early warning that scoring is falling behind.
For research context on how these models are trained and evaluated, see research and benchmarks.
Practical guidance and best practices
Topology and naming
- Use clear names such as
ingest.validateandingest.score. Include the domain and the action. - Keep one virtual host per environment or per team boundary.
- Declare topology from code or definitions files so environments stay identical.
- Avoid very large numbers of exclusive, auto-delete queues created per request unless you have tested the cost.
Durability and safety
- Use quorum queues for work that must not be lost.
- Mark messages persistent and use publisher confirms.
- Set a delivery limit and a dead letter exchange on every work queue.
- Acknowledge after the work is done, not before.
- Keep an odd number of nodes, usually three, for quorum queues.
Performance
- Tune prefetch to the task duration. Start low for slow tasks.
- Reuse connections and channels. Do not open a connection per message.
- Batch publishes and confirms when latency allows.
- Keep queues short. A healthy work queue is usually close to empty.
- Use lazy or stream types for very long backlogs, after testing.
- Compress large bodies if CPU is cheaper than network.
Security
- Create separate users with the least privileges per application and per virtual host.
- Enable TLS for client and inter-node traffic.
- Store credentials in a secrets manager such as HashiCorp Vault, not in code.
- Disable or change default accounts.
- Restrict the management interface to trusted networks. This fits a zero trust approach.
Operations and observability
- Export broker metrics and trace message flow with OpenTelemetry context in headers.
- Alert on queue depth, oldest message age, unacknowledged count, memory and disk alarms.
- Run on Kubernetes with an operator, or on dedicated virtual machines, but keep persistent storage fast and reliable.
- Test failure modes: kill a node, partition the network, fill a disk. Learn how the cluster behaves before production does it for you.
- Plan upgrades with the official compatibility notes and enable feature flags in order.
Deployment sketch
# Example Docker Compose fragment for local development only
services:
broker:
image: rabbitmq:management
hostname: broker.example.internal
ports:
- "5672:5672"
- "15672:15672"
environment:
RABBITMQ_DEFAULT_USER: dev_user
RABBITMQ_DEFAULT_PASS: change_me_locally
volumes:
- broker-data:/var/lib/rabbitmq
volumes:
broker-data: {}
For local work, Docker is the quickest route. Use real secrets handling for any shared environment.
Choosing client patterns
| Pattern | When to use it |
|---|---|
| Work queue | Distribute jobs among identical workers |
| Publish-subscribe | Notify many services of an event |
| Routing | Send to subsets by key |
| Topics | Route by hierarchical categories |
| Request-reply | A caller needs an answer from a worker, using reply-to and correlation identifier |
| Delayed retry | Retry later using TTL plus dead letter back to the main exchange |
Retry design with delayed requeue
A common need is to retry a failed job after a pause. A simple pattern uses two queues. The work queue dead letters failed messages into a wait queue. The wait queue has no consumers and a message time to live of, say, 30 seconds. When the time expires, the message dead letters back to the main exchange and tries again.
- Count attempts in a header so the job stops after a few tries.
- Use longer waits for each attempt to avoid hammering a struggling dependency.
- Send the final failure to a parking queue and alert a human.
Capacity planning checklist
- Estimate peak messages per second and average body size.
- Multiply by the retention you need for backlog during an outage.
- Add replication overhead for quorum queues.
- Leave headroom on disk for the broker to write without hitting alarms.
- Load test with realistic consumers, since a fast producer and a slow consumer is the usual failure.
Monitoring signals worth alerting on
| Signal | What it suggests |
|---|---|
| Queue depth rising | Consumers are slower than producers |
| Oldest message age rising | Work is waiting too long |
| Unacknowledged count high | Consumers are stuck or prefetch is too large |
| Redelivery rate high | Handlers are failing or crashing |
| Memory or disk alarm | Publishers are being blocked |
| Connection churn | Clients are reconnecting too often |
Testing messaging code
- Write unit tests for handlers without the broker, passing a plain message body.
- Write integration tests against a disposable broker in a container.
- Include a test that sends the same message twice to prove idempotency.
- Include a test that sends a malformed body to prove it reaches the dead letter queue.
Common mistakes
- Auto-acknowledging by default. With auto-ack, the broker considers the message done as soon as it is sent. A consumer crash loses the message. Use manual acknowledgements for important work.
- Forgetting durability on both sides. A durable queue with transient messages loses data on restart. A persistent message in a non-durable queue does too.
- Unlimited prefetch. Without a limit, one consumer can pull the whole backlog into memory and starve others.
- Endless requeue loops. A poison message that always fails and is always requeued can spin forever. Set a delivery limit and a dead letter route.
- Using one queue as a database. Queues are for transit. Letting millions of messages pile up hurts the broker.
- Huge message bodies. Sending whole tables through the broker wastes memory. Send references.
- Opening a connection per message. This is slow and can exhaust file descriptors.
- Ignoring flow control and alarms. When memory or disk alarms trigger, publishers are blocked. Applications must handle that gracefully.
- Assuming strict ordering. Competing consumers and redelivery break global order. Design for out-of-order handling or use a single consumer per ordered stream.
- Putting secrets in messages. Message bodies may be stored on disk and appear in logs and dead letter queues. Protect sensitive fields first.
- Skipping idempotency. At least once delivery means duplicates happen. Make handlers safe to repeat.
- Running a two node cluster. Consensus needs a majority. Use three or more nodes for quorum queues.
Frequently asked questions
What is RabbitMQ used for?
RabbitMQ is used to pass messages between programs so that they do not have to talk to each other directly. Common jobs include running background tasks, distributing work among many workers, broadcasting events to several services and handling request and reply between services. It is especially popular where routing rules are complex or where each message must be acknowledged individually.
Is RabbitMQ the same as Kafka?
No. RabbitMQ is a broker that routes messages into queues and removes them after they are acknowledged. Kafka is a distributed log that keeps records for a set time so that many readers can replay them. RabbitMQ is often chosen for task queues and flexible routing, while Kafka is often chosen for high-volume event streaming and analytics. RabbitMQ streams add some log-like behavior to RabbitMQ.
What is the difference between an exchange and a queue?
An exchange receives messages from producers and decides where they should go, based on its type and its bindings. A queue is where messages wait until a consumer takes them. Producers talk to exchanges, and consumers talk to queues. This split is what gives RabbitMQ its flexible routing.
Does RabbitMQ guarantee that messages are not lost?
It can give strong guarantees when configured well, but not by default in every setup. You need durable quorum queues, persistent messages, publisher confirms and manual acknowledgements. Even then, you should design consumers to be idempotent, because redelivery can cause duplicates. No broker removes the need for careful application design.
What are quorum queues?
Quorum queues are a replicated queue type that stores each message on a majority of nodes using a consensus protocol. They are designed for data safety and predictable behavior during node failures. They are the recommended choice for important work queues in modern versions, replacing the older mirrored classic queues.
How does RabbitMQ handle failed messages?
When a consumer rejects a message without requeue, or when a message expires or exceeds its delivery limit, the broker can send it to a dead letter exchange. From there it lands in a dead letter queue where engineers or a retry process can inspect it. This keeps bad messages from blocking healthy traffic.
Can RabbitMQ work with MQTT or other protocols?
Yes. Through plugins, RabbitMQ can accept MQTT, STOMP and web-based protocols, and newer versions include AMQP 1.0 support. This lets devices and services using different protocols share one broker. For large fleets of small sensors, a dedicated MQTT setup may still be a better fit.
How does RabbitMQ help machine learning pipelines?
It buffers and routes the work around a model. Data producers publish batches or file references, worker processes pull them and call the model, and results flow to storage or to other services. This protects model servers from bursts, allows retries and keeps stages independent. It does not train or run models itself.
Should I send whole tables through RabbitMQ?
Usually not. Large bodies strain memory and slow the broker. A better pattern is to store the table in object storage or a database and send a small message with a pointer, a checksum, a schema version and a dataset identifier. Workers then fetch the data directly.
How many nodes does a RabbitMQ cluster need?
For quorum queues, three nodes is the common minimum, because a majority must remain available for the queue to operate. Five nodes can tolerate more failures but add cost and replication overhead. A single node is fine for development but is a single point of failure in production.
Glossary
- Acknowledgement (ack): A consumer message telling the broker that a delivery was processed.
- AMQP: A messaging protocol with defined roles for exchanges, queues and bindings.
- Backpressure: A way to slow producers when consumers or the broker cannot keep up.
- Binding: A link between an exchange and a queue, often with a routing pattern.
- Broker: A server that receives, stores and forwards messages.
- Channel: A lightweight virtual connection inside a TCP connection.
- Competing consumers: Several workers reading from one queue to share load.
- Consumer: A program that receives messages.
- Dead letter exchange: An exchange that receives rejected, expired or over-delivered messages.
- Delivery limit: A cap on how many times a message may be redelivered.
- Durable: Describes an object that survives a broker restart.
- Exchange: The routing entry point for published messages.
- Idempotent: Safe to run more than once with the same result.
- Prefetch: The number of unacknowledged messages allowed per consumer.
- Producer: A program that publishes messages.
- Publisher confirm: A signal that the broker accepted a published message.
- Quorum queue: A replicated queue using majority agreement.
- Routing key: A label used to select queues at an exchange.
- Stream: A log-style queue type with offset-based reading.
- Virtual host: A namespace that separates sets of resources and permissions.
Summary
RabbitMQ is a mature message broker that routes messages from producers to consumers through exchanges, bindings and queues. It excels at task queues, flexible routing and reliable per-message handling, and it offers quorum queues and streams for stronger durability and replay. It is not a table engine or a model, but it plays a practical supporting role in pipelines for tabular foundation models: it buffers incoming row batches, distributes scoring, imputation and anomaly jobs, isolates bad inputs, and fans results out to downstream systems. Used with small messages, idempotent consumers, sensible prefetch, dead letter handling and sound security, it gives data teams a dependable backbone. Compare it with Apache Kafka and NATS before choosing, and pick the tool whose model matches how your data flows.
Related
It belongs to Event streaming in my stack, under Data engineering and lakehouse. Others in the same group: