KubeMQ
Client SDKsKotlinHow-to guidesQueues

Delay Policy

Send KubeMQ queue messages with staggered delays via QueueMessagePolicy using the Kotlin SDK.

Overview

A delay policy defers when a queued message becomes visible to consumers — you send it now, but nothing can receive it until a countdown you set expires. That's the mechanism behind retry-after-backoff, rate-limited notifications, "remind me in an hour" workflows, and staggering a burst of work so it doesn't hit downstream consumers all at once, all without standing up a separate scheduler.

It works entirely at send time: QueueMessagePolicy(delaySeconds = delay) attaches a delay to the message before it's passed to sendQueuesMessage. The broker starts the countdown the moment it accepts the message and simply excludes it from delivery until the timer elapses — after that it behaves like any other queued message, available to whichever consumer polls next.

Gotchas: the delay is a floor, not a guarantee — the message becomes eligible when the timer expires, but actual delivery still waits for a consumer to poll, so don't rely on it for precise scheduling. It's one-shot: there's no recurrence or cron-like behavior, so long or repeating delays need application logic on top. And it's independent of redelivery — a delayed message that's later nacked or times out after delivery follows normal visibility-timeout/retry rules, not the original send-time delay.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Kotlin SDK installed (implementation("io.kubemq.sdk:kubemq-sdk-kotlin:1.0.1"))

Code

DelayPolicyExample.kt
package io.kubemq.sdk.examples.queuesstream

import io.kubemq.sdk.client.KubeMQClient
import io.kubemq.sdk.queues.QueueMessagePolicy
import io.kubemq.sdk.queues.queueMessage
import kotlinx.coroutines.runBlocking

private const val ADDRESS = "localhost:50000"
private const val CLIENT_ID = "kotlin-queues-delay-policy"
private const val CHANNEL = "kotlin-queues.delay-policy"

fun main() = runBlocking {
    val client = KubeMQClient.queues {
        address = ADDRESS
        clientId = CLIENT_ID
    }

    client.use {
        try {
            client.createQueuesChannel(CHANNEL)

            // Send messages with different delay values
            val delays = intArrayOf(1, 3, 5)
            for (delay in delays) {
                client.sendQueuesMessage(queueMessage {
                    channel = CHANNEL
                    body = "Delay ${delay}s".toByteArray()
                    policy = QueueMessagePolicy(delaySeconds = delay)
                })
                println("Sent message with ${delay}s delay.")
            }

            // Poll as messages become available after their delay
            println("\nPolling as messages become available...")
            repeat(3) {
                val response = client.receiveQueuesMessages {
                    channel = CHANNEL
                    maxItems = 1
                    waitTimeoutMs = 10000
                    autoAck = true
                }
                if (response.messages.isNotEmpty()) {
                    println("  Received: ${String(response.messages.first().body)}")
                }
            }
        } finally {
            try { client.deleteQueuesChannel(CHANNEL) } catch (_: Exception) {}
        }
        println("Done.")
    }
}

How It Works

  • QueueMessagePolicy(delaySeconds = n) makes the message invisible for n seconds.
  • Messages with shorter delays become available first (1s, then 3s, then 5s).
  • The long waitTimeoutMs = 10000 allows the poll to wait for delayed messages to become available.
  • Useful for scheduled tasks, rate limiting, or retry backoff patterns.

Was this page helpful?

On this page