All Products
Search
Document Center

ApsaraMQ for RocketMQ:Send and subscribe to delayed messages

Last Updated:Mar 10, 2026

Delayed messages let you control when a message becomes available for consumption. The ApsaraMQ for RocketMQ broker holds a delayed message until a specified delivery time, then releases it to subscribers. Delayed messages are similar to delayed queues.

Common use cases:

  • Order timeout handling: Cancel an unpaid order after 30 minutes by sending a delayed message that triggers the cancellation logic.

  • Retry with backoff: Schedule a retry attempt after a fixed delay when an upstream dependency is temporarily unavailable.

  • Deferred notifications: Send a reminder or follow-up notification after a configurable waiting period.

For concepts and constraints, see Scheduled messages and delayed messages.

Prerequisites

Before you begin, make sure that you have:

How delayed messages work

  1. The producer creates a message and sets a delivery time using setStartDeliverTime().

  2. The broker receives the message and holds it until the specified delivery time.

  3. At the delivery time, the broker releases the message to the topic, making it available for consumers.

ParameterDetail
Time formatAbsolute timestamp in milliseconds (Unix epoch)
Minimum valueMust be later than the current time
Maximum delay40 days from the current time

Send delayed messages

The only difference from sending a normal message is one method call: msg.setStartDeliverTime(delayTime). This sets the absolute timestamp (in milliseconds) at which the broker delivers the message.

For more examples, see the ApsaraMQ for RocketMQ code library.

import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.SendResult;
import java.util.Date;
import java.util.Properties;

public class ProducerDelayTest {
    public static void main(String[] args) {
        Properties properties = new Properties();
        // Retrieve the AccessKey pair from environment variables.
        // Make sure ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set.
        properties.put(PropertyKeyConst.AccessKey, System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"));
        properties.put(PropertyKeyConst.SecretKey, System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));

        // Specify the TCP endpoint.
        // Find this value in the TCP Endpoint section of the Instance Details page
        // in the ApsaraMQ for RocketMQ console.
        properties.put(PropertyKeyConst.NAMESRV_ADDR, "<your-tcp-endpoint>");

        Producer producer = ONSFactory.createProducer(properties);
        // Call start() once before sending any messages.
        producer.start();

        Message msg = new Message(
                "<your-topic>",       // Topic created in the console
                "DelayMessageTag",    // Tag for consumer-side filtering, similar to a Gmail tag
                "Hello MQ".getBytes() // Message body in binary format.
                                      // ApsaraMQ for RocketMQ does not process message bodies.
                                      // Producer and consumer must agree on serialization.
        );
        // Optional: set a business key for message tracing.
        // The key should be globally unique when possible. Use it to query
        // or resend messages in the ApsaraMQ for RocketMQ console.
        msg.setKey("ORDERID_100");

        try {
            // Set the delivery time to 3 seconds from now.
            // The value is an absolute timestamp in milliseconds.
            // The maximum delay that you can specify is 40 days.
            long delayTime = System.currentTimeMillis() + 3000;
            msg.setStartDeliverTime(delayTime);

            // Send the message in synchronous transmission mode.
            // If no exception is thrown, the message is sent.
            SendResult sendResult = producer.send(msg);
            if (sendResult != null) {
                System.out.println(new Date() + " Send mq message success. Topic is:"
                        + msg.getTopic() + " msgId is: " + sendResult.getMessageId());
            }
        } catch (Exception e) {
            // Handle send failure: log, retry, or persist the message.
            System.out.println(new Date() + " Send mq message failed. Topic is:" + msg.getTopic());
            e.printStackTrace();
        }

        // Shut down the producer when the application exits.
        // For high-throughput scenarios, keep the producer running and reuse it.
        producer.shutdown();
    }
}

Replace the following placeholders with your actual values:

PlaceholderDescriptionExample
<your-tcp-endpoint>TCP endpoint from the Instance Details pagehttp://MQ_INST_xxxxx.mq-internet-access.mq-internet.aliyuncs.com:80
<your-topic>Topic name created in the consoleDelayTopic
Note

If you are new to ApsaraMQ for RocketMQ, see the Demo project to set up a working project before sending and receiving messages.

Subscribe to delayed messages

Subscribing to delayed messages works the same way as subscribing to normal messages. No special consumer configuration is required -- the delay logic is entirely on the producer side.

For the consumer sample code, see Subscribe to messages.

Next steps