Message Queue Patterns: P2P, Pub/Sub, and Request-Reply Explained
Message Queue Patterns: Point-to-Point vs Publish-Subscribe vs Request-Reply
Message queues enable asynchronous communication between distributed systems, decoupling services and improving resilience. Selecting the correct pattern determines system coupling, scalability, and delivery guarantees.
Point-to-Point (P2P)
The Point-to-Point pattern uses a Queue to establish a one-to-one relationship between a producer and a consumer.
Mechanics
- Producers send messages to a specific named queue.
- Messages are stored in the queue until consumed.
- Consumers compete for messages; each message is delivered to only one consumer.
- Once a message is acknowledged, it is removed from the queue.
Technical Characteristics
- Load Balancing: Multiple consumers can listen to the same queue to distribute load.
- Temporal Decoupling: The producer does not need to know if the consumer is online.
- Guarantee: "At-least-once" delivery. Exactly-once processing requires application-level idempotency or specific broker configurations (e.g., Kafka transactions).
- Ordering: The queue maintains FIFO order for delivery. While a single consumer processes messages sequentially, multiple consumers process in parallel, resulting in out-of-order completion.
Use Cases
- Task execution queues (e.g., image processing, email sending).
- Work distribution where strict ordering is required per processing thread.
Publish-Subscribe (Pub/Sub)
The Publish-Subscribe pattern uses a Topic to establish a one-to-many relationship between a publisher and subscribers.
Mechanics
- Publishers send messages to a specific topic.
- The messaging broker creates copies of the message.
- Subscribers receive a copy of every message sent to the topic.
- Subscribers use filtering (subscription criteria) to receive only relevant subsets of messages.
Technical Characteristics
- Fan-out: Efficiently delivers data to multiple consumers simultaneously.
- Spatial Decoupling: Publishers have no knowledge of subscriber existence or count.
- Ephemeral vs Durable: Non-durable subscriptions only receive messages sent while actively subscribed. Durable subscriptions ensure offline subscribers receive missed messages upon reconnection.
- Filtering: Implemented via broker-side routing (e.g., RabbitMQ topic exchanges matching routing keys) or consumer-side filtering (discarding irrelevant messages after receipt).
Use Cases
- Event notification systems (e.g., user updates, stock price feeds).
- Data synchronization across multiple disparate services.
Request-Reply
The Request-Reply pattern simulates synchronous request-response behavior over an asynchronous messaging infrastructure.
Mechanics
- The Client sends a request message to a designated queue.
- The message includes two critical properties: Reply-To (a temporary queue name) and CorrelationId (a unique identifier).
- The Server consumes the request, processes it, and sends the response to the queue specified in Reply-To.
- The Client listens on the temporary queue and matches the incoming CorrelationId to the original request.
Technical Characteristics
- Temporal Coupling: The client blocks or waits asynchronously for the response.
- Stateful: Requires the client to maintain pending request state.
- Bidirectional: Requires two distinct channels (request queue and reply queue).
Use Cases
- Remote Procedure Calls (RPC) where messaging middleware is required.
- Querying stateful services in an asynchronous architecture.
Message Lifecycle & Reliability
Persistence & Durability
Queue durability ensures the queue definition survives broker restarts. Message persistence ensures individual messages are written to disk rather than stored only in memory. Both are required to prevent data loss during a restart.
Time-to-Live (TTL)
TTL defines the expiration time for a message. If a message is not consumed within the specified TTL, it is removed from the queue. TTL can be applied per-message or configured as a policy for an entire queue to prevent stale data accumulation.
Dead Letter Queues (DLQ)
A DLQ is a secondary queue where messages are routed if they cannot be processed successfully. Common triggers include exceeding retry limits, message format validation failures, or processing exceptions. DLQs allow operators to inspect and reprocess failed messages without blocking the main processing pipeline.
Code Example
The following example demonstrates the Request-Reply pattern using a generic AMQP-style JavaScript implementation. It includes both the Server and Client implementations, queue assertion, error handling, and connection cleanup.
const amqp = require('amqplib');
const crypto = require('crypto');
// --- Server Implementation ---
async function rpcServer() {
try {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
const requestQueue = 'rpc_queue';
// Assert queue to ensure it exists and is durable
await channel.assertQueue(requestQueue, { durable: true });
channel.prefetch(1);
console.log(' [x] Awaiting RPC requests');
channel.consume(requestQueue, (msg) => {
const n = parseInt(msg.content.toString());
console.log(' [.] Received request:', n);
const response = n * 2; // Example processing logic
channel.sendToQueue(msg.properties.replyTo,
Buffer.from(response.toString()),
{ correlationId: msg.properties.correlationId }
);
channel.ack(msg);
});
} catch (error) {
console.error('Server Error:', error);
}
}
// --- Client Implementation ---
async function rpcClient() {
const connection = await amqp.connect('amqp://localhost');
const channel = await connection.createChannel();
try {
const requestQueue = 'rpc_queue';
// Assert request queue to prevent errors if it doesn't exist
await channel.assertQueue(requestQueue, { durable: true });
const replyQueue = await channel.assertQueue('', { exclusive: true }).then(q => q.queue);
const correlationId = crypto.randomUUID();
return new Promise((resolve, reject) => {
// Listen for the response
channel.consume(replyQueue, (msg) => {
if (msg.properties.correlationId === correlationId) {
console.log(' [.] Got response:', msg.content.toString());
channel.ack(msg);
resolve(msg.content.toString());
}
}, { noAck: false });
// Send the request
channel.sendToQueue(requestQueue,
Buffer.from('10'),
{ correlationId: correlationId, replyTo: replyQueue }
);
// Timeout to prevent resource leaks if no response is received
setTimeout(() => {
reject(new Error('Request timed out'));
}, 5000);
});
} catch (error) {
console.error('Client Error:', error);
throw error;
} finally {
await connection.close();
}
}
This code sets up a temporary exclusive queue for the reply, generates a unique Correlation ID, asserts the request queue exists, and implements error handling and connection cleanup.
Getting Started
- Define your coupling needs: Use P2P for work distribution (one consumer), Pub/Sub for broadcasting (many consumers), and Request-Reply for querying.
- Select your broker: Choose a broker that supports your required patterns (e.g., RabbitMQ excels at routing, Kafka excels at Pub/Sub streams).
- Configure Reliability: Enable persistence for critical data, set TTLs to manage queue bloat, and configure Dead Letter Queues (DLQ) to capture and analyze failed messages.
- Monitor depth: Track queue depth to prevent backpressure buildup that can crash consumers.
MatterAI builds frontier AI infrastructure for engineering teams — from inference-optimized models to autonomous coding agents and agentic code reviews.
Explore what we're building:
- Orbital IDE — Autonomous AI coding agent with background agents and deep codebase memory
- AI Code Reviews — Agentic pre-commit reviews across GitHub, GitLab, and Bitbucket
- Axon Models — Frontier-grade reasoning models at 70% lower inference cost
Share this Guide:
More Guides
Local LLMs in Your IDE: Connecting Ollama to Coding Agents and Autocomplete
Wire local models into VS Code, JetBrains, Cline, Continue, and Aider via the OpenAI-compatible API. Covers model routing, context budgets, tool calling with small models, and when a local model is the right choice for the job.
15 min readBuilding a Self-Hosted AI Stack: Ollama, Open WebUI, and Local RAG
Stand up a fully self-hosted AI stack on a single machine: Ollama for inference, Open WebUI as the chat interface, local embeddings for RAG, and a reverse proxy for secure access. No cloud dependency, no data leaving your network.
17 min readTop 5 Open-Source Coding Models to Run on Your Mac (2026)
The best local coding models for Apple Silicon in 2026, ranked by quality per gigabyte of unified memory. Covers qwen3-coder, devstral, gpt-oss, and more with real pull tags, sizes, and context windows.
14 min readRunning LLMs Locally: GGUF, Quantization, and Memory Planning
Learn the GGUF format, the quantization ladder from Q2 to FP16, and the exact memory math for running models on Apple Silicon and NVIDIA GPUs. Includes Ollama and llama.cpp tuning for KV cache and context.
15 min readOllama vs vLLM vs llama.cpp: Choosing the Right Local LLM Runtime
Compare the three dominant local LLM runtimes on architecture, throughput, hardware, and deployment context. Includes benchmark data, a decision framework, and a migration path from Ollama to vLLM.
16 min readContinue Reading
Local LLMs in Your IDE: Connecting Ollama to Coding Agents and Autocomplete
Wire local models into VS Code, JetBrains, Cline, Continue, and Aider via the OpenAI-compatible API. Covers model routing, context budgets, tool calling with small models, and when a local model is the right choice for the job.
15 min readBuilding a Self-Hosted AI Stack: Ollama, Open WebUI, and Local RAG
Stand up a fully self-hosted AI stack on a single machine: Ollama for inference, Open WebUI as the chat interface, local embeddings for RAG, and a reverse proxy for secure access. No cloud dependency, no data leaving your network.
17 min readTop 5 Open-Source Coding Models to Run on Your Mac (2026)
The best local coding models for Apple Silicon in 2026, ranked by quality per gigabyte of unified memory. Covers qwen3-coder, devstral, gpt-oss, and more with real pull tags, sizes, and context windows.
14 min readShip Faster. Ship Safer.
Join thousands of engineering teams using MatterAI to autonomously build, review, and deploy code with enterprise-grade precision.
