Skip to main content

Messaging – Publish

Overview

The publish API allows your Swift 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 Swift 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:

    • [String: Any] (JSON dictionary/object)
    • String
    • NSNumber (Int, Double, Float, etc.)

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

Return Value

publish(topic, message) is an async function that returns a Bool:

  • 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 an async function, it must be called with await from an async context.


Code Example

import Realtime

Task {
do {
// JSON Message (Dictionary)
let jsonMessage: [String: Any] = [
"orderId": "12345",
"amount": 250,
"currency": "USD"
]
let success = try await realtime.publish(topic: "orders.created", message: jsonMessage)

// String Message
let success2 = try await realtime.publish(topic: "orders.created", message: "Order #123 created!")

// Number Message
let success3 = try await realtime.publish(topic: "orders.created", message: 123)

if !success {
print("Message queued for resend or client disconnected from Relay Network")
}
} catch {
print("Error publishing message: \(error)")
}
}

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 iOS app 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 Realtime

class MessageResendListener: MessageListener {
func onMessage(_ message: Any) {
// message is an array of dictionaries containing resent message information
if let messages = message as? [[String: Any]] {
for msg in messages {
print("Resent message: \(msg)")
}
}
}
}

Task {
let resendListener = MessageResendListener()
try await realtime.on(topic: SystemEvent.messageResend.rawValue, listener: resendListener)
}

Structure of the data sent to the callback:

// The data is an array of dictionaries [[String: Any]]
// Each dictionary contains:
[
"topic": String, // Topic the message was sent to
"message": Any, // Your message (Dictionary, String, or Number)
"resent": Bool // Whether the message was successfully resent
]

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 ✌️