Delayed Messages
Send KubeMQ Queue messages with a delivery delay using the Java SDK so consumers receive them after a set interval.
Which to use
This is the task-oriented guide for sending delayed messages — send one with a delivery delay, confirm it's hidden, then receive it once the delay expires. For the delayInSeconds builder option reference and its edge cases, see Delay Policy.
Overview
A delivery delay holds a queue message out of consumers' reach for a fixed window after it's sent — the message is accepted and persisted immediately, but invisible to pollers until the delay expires. It's the building block for scheduled work — a reminder to fire in an hour, a retry with back-off, a task queued for off-peak processing — without standing up a separate scheduler or cron service.
Set it with .delayInSeconds(...) on the QueueMessage builder before sending; the broker does the waiting. A poll against the channel before the delay elapses (via receiveQueueMessages) simply returns zero messages — it isn't hidden in a separate place, it's the same queue, just not yet eligible for delivery. Once the delay window passes, the next poll retrieves it normally.
Gotchas: the delay is set once at send time, per message, and can't be extended or shortened afterward — if you need a different wait, send a new message. A long delay still counts as an in-flight, persisted message, so it survives a broker restart, but it also occupies queue storage for the whole waiting period. Don't confuse this with a visibility timeout after delivery — that's a separate mechanism for redelivery on failed acknowledgment, not initial availability.
Prerequisites
- KubeMQ server running on
localhost:50000 - Java SDK installed (
implementation 'io.kubemq.sdk:kubemq-sdk-Java:3.1.1'(Gradle) or Maven dependency from Getting Started)
Code
package io.kubemq.example.queues;
import io.kubemq.sdk.queues.*;
import java.util.UUID;
/**
* Delayed Messages Example
*
* Demonstrates sending messages with a delay before they become available for consumption.
*/
public class DelayedMessagesExample {
private static final String ADDRESS = "localhost:50000";
private static final String CLIENT_ID = "java-queues-delayed-messages-client";
private static final String CHANNEL = "java-queues.delayed-messages";
public static void main(String[] args) throws InterruptedException {
// Create a queues client connected to the KubeMQ server
try (QueuesClient client = QueuesClient.builder().address(ADDRESS).clientId(CLIENT_ID).build()) {
// Create the queue channel
client.createQueuesChannel(CHANNEL);
// Send a message with delay (not available for consumption until delay expires)
int delaySeconds = 3;
client.sendQueueMessage(QueueMessage.builder()
.id(UUID.randomUUID().toString()).channel(CHANNEL)
.body(("Delayed by " + delaySeconds + "s").getBytes())
.delayInSeconds(delaySeconds).build());
System.out.println("Sent message with " + delaySeconds + "s delay.");
// Try to receive immediately (message not yet available)
System.out.println("Trying to receive immediately...");
QueuesPollResponse resp1 = client.receiveQueueMessages(QueuesPollRequest.builder()
.channel(CHANNEL).pollMaxMessages(1).pollWaitTimeoutInSeconds(1).autoAckMessages(true).build());
System.out.println("Messages available: " + resp1.getMessages().size() + " (expected 0)");
// Wait for the delay to expire
System.out.println("Waiting for delay to expire...");
Thread.sleep((delaySeconds + 1) * 1000);
// Receive the message after delay has expired
QueuesPollResponse resp2 = client.receiveQueueMessages(QueuesPollRequest.builder()
.channel(CHANNEL).pollMaxMessages(1).pollWaitTimeoutInSeconds(2).autoAckMessages(true).build());
if (!resp2.getMessages().isEmpty()) {
System.out.println("Received after delay: " + new String(resp2.getMessages().get(0).getBody()));
}
// Clean up resources
client.deleteQueuesChannel(CHANNEL);
}
}
}
How It Works
delayInSeconds(3)on theQueueMessagetells the broker to hold the message for 3 seconds before making it available for consumers.- The first poll (1-second timeout) returns empty because the delay has not expired; the second poll after
Thread.sleep((delaySeconds + 1) * 1000)finds the message available. - The delay is set per-message at publish time; different messages on the same channel can have different delays.
Related
- Delay Policy — field-level reference for
delayInSeconds - Pattern overview
- Java SDK Reference
- Send & Receive
- Ack All
Was this page helpful?