Skip to content

Commit e47cbca

Browse files
committed
Document the x-modulus-hash exchange type
This commit adds documentation for the built-in `x-modulus-hash` exchange. It adds a dedicated page explaining its core features: stable routing, weighted routing, and how it compares to the consistent hash exchange. It also adds a bullet point to the message ordering section in `queues.md` to highlight the common use case of using `x-modulus-hash` with Single Active Consumer (SAC) to process messages concurrently while preserving order for each domain entity. Docs for rabbitmq/rabbitmq-server#15849
1 parent f975274 commit e47cbca

4 files changed

Lines changed: 63 additions & 0 deletions

File tree

docs/exchanges.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ RabbitMQ ships with multiple exchange types:
6767
* Direct: covered in [tutorial 4](https://www.rabbitmq.com/tutorials)
6868
* Default direct exchange: a built-in direct exchange with special characteristics
6969
* [Local Random](./local-random-exchange)
70+
* [Modulus Hash](./modulus-hash-exchange)
7071
* [JMS Topic](https://github.com/rabbitmq/rabbitmq-server/blob/main/deps/rabbitmq_jms_topic_exchange/README.md)
7172
* [Consistent Hashing exchange](https://github.com/rabbitmq/rabbitmq-server/tree/main/deps/rabbitmq_consistent_hash_exchange)
7273
* [Random exchange](https://github.com/rabbitmq/rabbitmq-server/tree/main/deps/rabbitmq_random_exchange)

docs/modulus-hash-exchange.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
title: Modulus Hash Exchange
3+
---
4+
<!--
5+
Copyright (c) 2005-2026 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
6+
7+
All rights reserved. This program and the accompanying materials
8+
are made available under the terms of the under the Apache License,
9+
Version 2.0 (the "License”); you may not use this file except in compliance
10+
with the License. You may obtain a copy of the License at
11+
12+
https://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing, software
15+
distributed under the License is distributed on an "AS IS" BASIS,
16+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
See the License for the specific language governing permissions and
18+
limitations under the License.
19+
-->
20+
21+
# Modulus Hash Exchange
22+
23+
## Overview {#overview}
24+
25+
The `x-modulus-hash` exchange is a built-in exchange type in RabbitMQ that distributes messages across bound queues based on a hash of the routing key. It is designed to partition messages across a number of regular queues (shards) while guaranteeing stable routing.
26+
27+
When a message is published to this exchange, it hashes the message's routing key and applies a `Hash mod N` operation to pick the destination queue, where `N` is the total number of bound destinations.
28+
29+
**Note:** This exchange ignores the values of the binding keys.
30+
31+
## Stable Routing {#stable-routing}
32+
33+
A key feature of the `x-modulus-hash` exchange is that it guarantees **stable routing**. As long as the bindings to the exchange remain the same, messages with the same routing key will always be routed to exactly the same destination queue, even across node restarts.
34+
35+
This makes it an excellent choice for use cases where message ordering matters for a specific domain entity (e.g. an order ID), but you still want to process messages concurrently across multiple consumers.
36+
37+
### Concurrent Processing with Message Ordering
38+
39+
A common pattern is to bind `N` queues to an `x-modulus-hash` exchange and enable the [Single Active Consumer (SAC)](./consumers#single-active-consumer) feature on each queue. This provides:
40+
* **Message ordering:** Thanks to stable routing, all messages for a specific routing key end up in the same queue. SAC ensures they are processed in order.
41+
* **Concurrent consumption:** `N` application instances can process messages in parallel, each consuming from a different queue.
42+
* **Fault tolerance:** If an active consumer crashes, the broker will automatically deliver messages to another consumer attached to that queue.
43+
44+
## Weighted Routing {#weighted-routing}
45+
46+
The `x-modulus-hash` exchange also supports **weighted routing** implicitly. If a user binds the exact same queue `M` times to the same exchange instance (using different dummy binding keys, since the binding key is ignored for routing), the queue will have an `M / N` probability of receiving any given message. This allows you to easily distribute more load to specific queues if needed.
47+
48+
## Comparison with Consistent Hash Exchange
49+
50+
RabbitMQ also provides a [Consistent Hash Exchange](https://github.com/rabbitmq/rabbitmq-server/blob/main/deps/rabbitmq_consistent_hash_exchange/README.md) plugin. While both can partition messages based on routing keys, they have different trade-offs:
51+
52+
* **Modulus Hash Exchange:** Simpler, built-in, and guarantees stable routing. However, if you add or remove queues (changing `N`), the routing for almost all keys will be reshuffled.
53+
* **Consistent Hash Exchange:** Requires enabling a plugin and manages a more complex hash ring. It minimizes reshuffling when queues are added or removed, making it better for dynamic topologies.
54+
55+
If your topology is static and you need strict message ordering guarantees, the `x-modulus-hash` exchange is recommended.

docs/queues.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ To keep order with queues:
251251
* For quorum queues, set a [delivery limit](./quorum-queues#poison-message-handling).
252252
This ensures messages are requeued at the front of the queue.
253253
* AMQP 0-9-1: don’t use `basic.get`. When stopping a consumer, prefer closing the [channel](./channels) over `basic.cancel`.
254+
* If you need to process messages concurrently while preserving order for each domain entity (e.g. per order ID), you can use the
255+
[`x-modulus-hash` exchange](./modulus-hash-exchange) to partition messages across multiple queues, each with a single active consumer.
254256

255257
## Durability {#durability}
256258

sidebarsDocs.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,11 @@ const sidebars = {
171171
id: 'local-random-exchange',
172172
label: 'Local random exchange',
173173
},
174+
{
175+
type: 'doc',
176+
id: 'modulus-hash-exchange',
177+
label: 'Modulus hash exchange',
178+
},
174179
{
175180
type: 'doc',
176181
id: 'connection-blocked',

0 commit comments

Comments
 (0)