Backend Development 10 min read

Mastering RocketMQ Delayed Messages: Principles, Implementation, and Best Practices

This tutorial explains RocketMQ's delayed message feature, covering its core concepts, implementation using a time‑wheel algorithm, step‑by‑step usage instructions, practical code examples, and important considerations for reliable scheduling in distributed backend systems.

Architecture & Thinking
Architecture & Thinking
Architecture & Thinking
Mastering RocketMQ Delayed Messages: Principles, Implementation, and Best Practices

1 Review

Previously we learned the basics of RocketMQ and its powerful capabilities as a message middleware. RocketMQ supports several distinct message types:

Ordinary messages

Scheduled/Delayed messages

Ordered messages

Transactional messages

This article introduces the execution principle, usage method, and application scenarios of scheduled/delayed messages.

2 Implementation of Scheduled/Delayed Messages

2.1 🚀 What is a delayed message

A delayed message is an advanced message type provided by Apache RocketMQ. After a message is sent to the server, it becomes consumable only after a specified time, enabling distributed delayed scheduling. Typical scenarios include:

1. 🛒 Order timeout handling: automatically close an order if payment is not received within a set period, e.g., 30 minutes.

2. ⏰ Scheduled task execution: run daily data syncs or periodic device status checks.

3. 🔄 Retry mechanism: re‑attempt message consumption after a failure with a delay.

Compared with traditional cron jobs, RocketMQ's delayed messages are more efficient and reliable in distributed environments because they natively support high concurrency and horizontal scaling.

2.2 🔍 How delayed messages are implemented

RocketMQ implements delayed messages in three steps:

1. Message storage : When a producer sends a delayed message, RocketMQ stores it in an internal topic named SCHEDULE_TOPIC_XXXX instead of delivering it directly to the target topic. This internal topic acts as a vault for delayed messages.

2. Time‑wheel algorithm : RocketMQ maintains a time‑wheel that assigns messages to slots based on their delay. For example, a 10‑second delay goes to the 10‑second slot, a 1‑hour delay to the 1‑hour slot. The wheel rotates like a clock; when it reaches a slot, the messages in that slot are awakened and re‑delivered to the target topic.

3. Periodic scanning : A background thread in the broker scans the time‑wheel every 100 ms. If a message's delay has expired, it is immediately dispatched to the target topic for consumption.

2.3 📌 Message lifecycle

1. Initialization: The producer creates the message and prepares it for sending.

2. Delayed state: After being sent, the broker stores the message in a dedicated delayed storage instead of building a normal index.

3. Ready for consumption: When the scheduled time arrives, the broker rewrites the message to the regular storage engine, making it visible to consumers.

4. Consuming: The consumer retrieves the message and processes it according to business logic. The broker waits for the consumer to acknowledge; if no response is received within a timeout, RocketMQ retries the message.

5. Consumption commit: After processing, the consumer reports the result. RocketMQ retains all messages by default, marking them as consumed but not deleting them until the retention period expires or storage pressure requires cleanup.

6. Message deletion: RocketMQ periodically removes the oldest messages based on its retention policy.

image
image

3 🛠️ How to use delayed messages? Practical guide

3.1 Sending delayed messages

Sending a delayed message in code is straightforward and involves two steps:

1. Set the delay level : RocketMQ provides 18 predefined delay levels ranging from 1 second to 2 hours. Example:

<code>Message message = new Message("OrderTopic", "订单超时提醒".getBytes());
message.setDelayTimeLevel(3); // level 3 corresponds to 10 seconds
producer.send(message);
</code>

2. Custom delay time (advanced) : In RocketMQ 5.0+ you can set an explicit timestamp:

<code>long delayTime = System.currentTimeMillis() + 10 * 60 * 1000; // 10 minutes later
message.setDeliverTimestamp(delayTime);
</code>

3.2 Consumer receiving messages

The consumer does not need special configuration; simply subscribe to the target topic as with ordinary messages:

<code>@RocketMQMessageListener(topic = "OrderTopic", consumerGroup = "order_group")
public class OrderConsumer implements RocketMQListener<String> {
    @Override
    public void onMessage(String message) {
        System.out.println("Received delayed message: " + message);
        // handle order timeout logic...
    }
}
</code>

4 ⚠️ Precautions when using delayed messages

1. Fixed delay levels : The open‑source version only supports the predefined 18 levels; arbitrary delays (e.g., 7 seconds or 1 day) are not possible. For more flexibility, combine with external schedulers or use the commercial edition.

The 18 levels are:

<code>1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
</code>

2. Maximum delay of 24 hours : By default, the longest delay is 24 hours. Extending beyond this requires broker configuration changes or chaining multiple delays.

3. Message accumulation : Excessive delayed messages may accumulate in the broker's memory or disk, affecting performance. Monitor the accumulation of SCHEDULE_TOPIC_XXXX regularly.

image
image

5 🌰 Real‑world case: Automatic order closure

Assume an e‑commerce system where an order must be closed if not paid within 30 minutes. Using RocketMQ delayed messages:

Send delayed message : When the user places an order, send a delayed message with a 30‑minute delay containing the order ID.

Consumer processing : After 30 minutes, the consumer receives the message, checks the order status, and if unpaid, calls the API to close the order.

This approach avoids heavy database polling while ensuring timely order closure.

💡 Summary

RocketMQ's delayed message feature is a compact yet powerful tool that leverages a time‑wheel algorithm and scheduled scanning to achieve efficient and reliable delayed delivery. It suits use cases such as order timeout handling, scheduled notifications, and IoT device timeout detection. When using it, be aware of its limitations—fixed delay levels and a 24‑hour maximum—and combine it with other solutions when necessary.

backendJavaschedulingMessage QueueRocketMQDelayed Message
Architecture & Thinking
Written by

Architecture & Thinking

🍭 Frontline tech director and chief architect at top-tier companies 🥝 Years of deep experience in internet, e‑commerce, social, and finance sectors 🌾 Committed to publishing high‑quality articles covering core technologies of leading internet firms, application architecture, and AI breakthroughs.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.