Skip to main content

Messaging – Publish

Overview

The publish API allows your Kotlin application to send messages to a specific RelayX topic.

Publishing is the primary way data enters the RelayX messaging system. When a message is published to a topic, it is immediately routed to all active subscribers of that topic. This mechanism is used to broadcast events, state changes, telemetry, or notifications across different parts of a system.

The publish operation is intentionally simple. It does not wait for subscribers to process the message and does not coordinate delivery across consumers. Once a message is accepted by the RelayX backend, delivery is handled asynchronously.

This page explains how publishing works in the Kotlin SDK, what the publish call does at runtime, and how to handle edge cases such as reconnects and failures.


How This Works

When you call publish(topic, message):

  1. The SDK validates the topic name locally.
  2. The message payload is serialized.
  3. If the client is connected, the message is sent immediately to the RelayX backend.
  4. If the client is reconnecting, the message is placed into an offline buffer.
  5. Once accepted by the backend, the message is delivered to all matching subscribers.

Publishing is fire-and-forget. The SDK does not wait for subscribers, acknowledgements, or downstream processing.

RelayX provides at-least-once delivery semantics. Messages may be delivered more than once to subscribers if failures occur during handling, but messages are never silently dropped once accepted by the backend.


API Usage

publish(topic, message)

Publishes a message to the given topic.

Required Parameters

  • topic (string)

    • The topic to publish to. The topic must follow RelayX topic naming rules and must not be a reserved system topic.
    • More information here
  • message (Any) The message payload. Supported types include:

    • JsonObject (com.google.gson.JsonObject)
    • JsonArray (com.google.gson.JsonArray)
    • String
    • Number (Int, Long, Double, Float, etc.)
    • Boolean

The SDK does not enforce a schema. Producers and consumers must agree on payload structure.

Return Value

publish(topic, message) is a suspend function that returns a Boolean:

  • true The message has been sent.

  • false One of the following occurred:

    • The client is reconnecting and the message was stored offline.
    • The connection is closed.

A false return value does not mean the message is lost.

Note: Since publish() is a suspend function, it must be called from a coroutine scope.


Code Example

import com.google.gson.JsonObject
import kotlinx.coroutines.runBlocking

runBlocking {
// JSON Message
val jsonMessage = JsonObject().apply {
addProperty("orderId", "12345")
addProperty("amount", 250)
addProperty("currency", "USD")
}
val success = realtime.publish("orders.created", jsonMessage)

// String Message
val success2 = realtime.publish("orders.created", "Order #123 created!")

// Number Message
val success3 = realtime.publish("orders.created", 123)

// Boolean Message
val success4 = realtime.publish("orders.created", true)

if (!success) {
println("Message queued for resend or client disconnected from Relay Network")
}
}

Failure & Edge Cases

Invalid Topics

publish() throws an error if:

  • The topic name is invalid.
  • The topic is a system-reserved topic.
  • The client doesn't have permissions to publish to the specified topic. More information here.
  • Publish attempt is made when allowed message quota (hard limit with no extra messages) has exceeded.

These errors must be caught by the application.


Reconnecting State

If the client is reconnecting:

  • publish() returns false.
  • The message is stored in an offline buffer.
  • The buffer is retained for up to 2 minutes.

When the client reconnects successfully, buffered messages are automatically republished.

If reconnection fails and the connection closes permanently, buffered messages are discarded.


Message Limits

Publishing may fail if message limits are exceeded. This is for plans with a message limit and no extra messages available.

In this case, publish() throws an error indicating the limit has been reached.


Process Crashes

If the Kotlin process crashes:

  • In-memory buffered messages are lost.
  • No resend occurs after restart.

Applications that require durability must persist messages externally.


Message Republish Confirmation

To receive confirmation that buffered messages were resent after reconnect:

  • Subscribe to the MESSAGE_RESEND system topic.
  • The SDK emits a list of objects describing republished messages.
import relay.Realtime
import kotlinx.coroutines.runBlocking

runBlocking {
realtime.on(Realtime.MESSAGE_RESEND) { data ->
println(data)
}
}

Structure of the data sent to the callback:

// The data is a List<OfflineMessage>
// Each OfflineMessage contains:
data class OfflineMessage(
val msg: Message, // The original message
val resent: Boolean // Whether the message was successfully resent
)

// Where Message contains:
data class Message(
val id: String?, // Message ID
val room: String?, // Topic the message was sent to
val message: Any?, // Your message (JsonObject | JsonArray | String | Number | Boolean)
val start: Long? // Timestamp when message was created
)

This mechanism is optional and intended for observability.


Common Mistakes

Assuming publish Waits for Delivery

publish() does not wait for subscribers or acknowledgements.


Publishing to Wildcard Topics

Publishing to wildcard topics does not throw an error, but subscribers matching the pattern will not receive the message.


Ignoring false Return Values

A false return value indicates offline buffering.


Notes & Limitations

  • Publishing is non-blocking.
  • Offline buffering is in-memory and time-limited.
  • Message ordering is enforced per topic by the backend.
  • The SDK does not retry publishes after permanent disconnection.


Need Help?

Join our Discord server, post your concern & someone from our team will help you out ✌️