Retained messages
Persist the last message on a topic so new subscribers receive it immediately.
Retained messages let the broker store the last message on a topic so new subscribers receive it immediately. Use them when "current state" matters more than every individual update, for example agent presence, last known state, or configuration values.
How it works
1. Publisher sends retained message
-> Broker stores it
2. New subscriber connects and subscribes
-> Broker immediately delivers retained message
3. Publisher sends new retained message
-> Broker replaces stored message
-> Delivers to current subscribersWithout retained messages
| Step | Result |
|---|---|
| Publisher publishes "online" | Delivered to current subscribers only |
| Time passes | No record kept |
| New subscriber connects | Waits for the next publish, sees nothing in the meantime |
With retained messages
| Step | Result |
|---|---|
| Publisher publishes "online" with retain | Broker stores the message |
| Time passes | Stored value persists |
| New subscriber connects | Immediately receives "online" |
Publishing retained messages
Set the retain flag to true when publishing.
JavaScript
const mqtt = require('mqtt');
const client = mqtt.connect('mqtts://mqtt.cloudsignal.app:8883', {
username: 'user@org-id',
password: 'password'
});
// Publish with retain flag
client.publish('agents/agent-001/state', 'online', {
retain: true,
qos: 1
});Python
import paho.mqtt.client as mqtt
client = mqtt.Client()
client.username_pw_set('user@org-id', 'password')
client.tls_set()
client.connect('mqtt.cloudsignal.app', 8883)
# Publish with retain flag
client.publish('agents/agent-001/state', 'online', retain=True, qos=1)MQTTX
- Enter your message in the publish area
- Check the Retain checkbox
- Click Publish
Receiving retained messages
Retained messages are delivered automatically when you subscribe. No special handling required:
client.on('message', (topic, payload, packet) => {
console.log(`Topic: ${topic}`);
console.log(`Message: ${payload.toString()}`);
console.log(`Is retained: ${packet.retain}`);
});
client.subscribe('agents/agent-001/state');
// If a retained message exists, it's delivered immediatelyThe retain flag in received messages indicates whether the message was stored on the broker (retained) or published live.
Use cases
Agent presence
Publish presence as retained so new dashboards immediately see current state:
// Agent publishes its status (retained)
client.publish('agents/agent-001/state', 'online', { retain: true });
// Dashboard subscribes and immediately gets state
// without waiting for next status update
client.subscribe('agents/+/state');Last known value
Publish retained snapshots so subscribers always have the latest value:
// Agent publishes every 10 seconds (retained)
setInterval(() => {
const snapshot = currentSnapshot();
client.publish('agents/agent-001/state', JSON.stringify(snapshot), {
retain: true
});
}, 10000);
// Mobile app connects and immediately gets last snapshot
client.subscribe('agents/agent-001/state');Configuration
Store configuration that agents should receive on connect:
// Backend publishes agent config (retained)
client.publish('agents/agent-001/config', JSON.stringify({
reportInterval: 30,
thresholds: { min: 0, max: 100 }
}), { retain: true });
// Agent connects and immediately receives its config
client.subscribe('agents/agent-001/config');Presence
Track who's currently online:
// User comes online
client.publish('presence/user-123', 'online', { retain: true });
// User goes offline (or use last will)
client.publish('presence/user-123', 'offline', { retain: true });
// New user checks who's online
client.subscribe('presence/#');
// Receives retained status for all usersClearing retained messages
To remove a retained message, publish an empty payload with the retain flag:
// Clear the retained message
client.publish('agents/agent-001/state', '', { retain: true });After clearing:
- No retained message exists for that topic
- New subscribers won't receive anything until a new message is published
Retained messages vs. QoS
Retained messages and QoS are independent features:
| Feature | Purpose |
|---|---|
| Retain | Store last message for new subscribers |
| QoS | Delivery guarantee for message transmission |
You can combine them:
// Retained + QoS 1: Store last value AND guarantee delivery
client.publish('agents/agent-001/state', 'online', {
retain: true,
qos: 1
});Best practices
Do retain
| Topic | Why retain |
|---|---|
Agent presence (online/offline) | New subscribers see current presence |
| Latest state snapshot | Last known value is meaningful on connect |
| Configuration values | Clients pick up config on subscribe |
| Current resource state | State is more useful than every change event |
Don't retain
| Topic | Why not |
|---|---|
| Events or logs | Historical, not current state |
| Commands | Should be transient |
| Chat messages | Not "last known value" |
| Notifications | One-time delivery |
Topic design for retained messages
Structure topics so retained messages make sense:
Good for retain:
agents/{id}/state -> "online" (current state)
agents/{id}/snapshot -> {...} (last known value)
config/{id}/settings -> {...} (current config)
Bad for retain:
events/{id}/log -> Single event, not state
notifications/{id} -> One-time alertCloudSignal message retention
CloudSignal stores retained messages persistently. Your retained messages survive broker restarts and will be delivered to new subscribers.
Message retention limits depend on your plan:
| Plan | Retention period |
|---|---|
| Free | 7 days |
| Pro | 30 days |
| Enterprise | Custom |
After the retention period, retained messages are automatically cleared.
Next steps
- QoS levels - Delivery guarantees
- Topics & wildcards - Topic design
- How CloudSignal works - System architecture