All Products
Search
Document Center

ApsaraMQ for RocketMQ:Send and receive scheduled messages

Last Updated:Mar 11, 2026

Some business scenarios require messages to be delivered at a specific future time rather than immediately. For example, an e-commerce platform needs to cancel unpaid orders after 30 minutes, or a monitoring system needs to trigger periodic health checks. Scheduled messages in ApsaraMQ for RocketMQ let you set a delivery timestamp on each message so the broker holds it and delivers it to consumers at the specified time.

This topic provides sample code for sending and receiving scheduled messages by using the TCP client SDK for Java.

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

Note

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

Use cases

  • Order timeout handling: Send a scheduled message set to the payment deadline when a user places an order. If the order is still unpaid when the message is delivered, cancel it automatically.

  • Periodic task triggering: Schedule operations such as daily file cleanup or periodic data synchronization by sending messages with future delivery times.

How scheduled messages work

  1. The producer sets a future delivery timestamp on a message by calling msg.setStartDeliverTime(timestamp).

  2. The broker holds the message until the specified timestamp.

  3. At the scheduled time, the broker delivers the message to subscribed consumers.

Time-setting rules:

RuleBehavior
Timestamp formatMillisecond-level Unix timestamp. Convert your target delivery time to milliseconds since epoch.
Past timestampThe message is delivered immediately.

Prerequisites

Before you begin, make sure you have:

Send a scheduled message

The following example sends a message with a future delivery timestamp. The msg.setStartDeliverTime(timestamp) method tells the broker when to deliver the message.

Replace the placeholders with your actual values:

PlaceholderDescriptionExample
<your-topic>Target topic namemy-scheduled-topic
<your-tag>Message tag for consumer filteringpayment-timeout
<your-message-body>Message content as a byte array"Hello MQ".getBytes()
<your-message-key>Business-specific unique identifierORDERID_100
<your-tcp-endpoint>TCP endpoint from the Instance Details page in the ApsaraMQ for RocketMQ console--
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.text.SimpleDateFormat;
import java.util.Properties;

public class ProducerDelayTest {
    public static void main(String[] args) {
        Properties properties = new Properties();
        // Load AccessKey pair from environment variables
        properties.put(PropertyKeyConst.AccessKey, System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"));
        properties.put(PropertyKeyConst.SecretKey, System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        // TCP endpoint from 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
                "<your-tag>",              // Tag for consumer-side filtering
                "<your-message-body>".getBytes()  // Message body in bytes
        );

        // Optional: set a business key for message tracing in the console
        msg.setKey("<your-message-key>");

        try {
            // Set the delivery timestamp (milliseconds since epoch)
            // Example: deliver at 2026-03-15 10:30:00
            long deliverTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                    .parse("2026-03-15 10:30:00")
                    .getTime();
            msg.setStartDeliverTime(deliverTime);

            SendResult sendResult = producer.send(msg);
            System.out.println("Message Id:" + sendResult.getMessageId());
        } catch (Exception e) {
            // Handle send failure: retry or persist the message
            System.out.println("Send failed. Topic: " + msg.getTopic());
            e.printStackTrace();
        }

        // Shut down the producer when the application exits.
        // To send messages frequently, keep the producer running instead of
        // shutting it down after each send.
        producer.shutdown();
    }
}

Key points:

  • setStartDeliverTime(long timestamp) accepts a millisecond-level Unix timestamp. The broker holds the message until this time.

  • Call producer.start() once before sending. For high-throughput scenarios, reuse the same producer instance rather than creating a new one for each message.

  • msg.setKey() is optional but recommended for tracing messages by business ID in the ApsaraMQ for RocketMQ console.

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

Subscribe to scheduled messages

Subscribe to scheduled messages the same way as normal messages. No special subscription logic is required -- the broker delivers the message to consumers when the scheduled timestamp arrives.

For the subscription code, see Subscribe to messages.

Best practices

  • Set unique message keys. The message key (setKey) should be globally unique when possible. Use it to look up messages in the ApsaraMQ for RocketMQ console if delivery issues occur.

  • Reuse the producer instance. Call producer.shutdown() only when the application exits. Repeatedly creating and destroying producers wastes memory.

Related topics