CloudSignal Docs
GuidesMQTT Fundamentals

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 subscribers

Without retained messages

StepResult
Publisher publishes "online"Delivered to current subscribers only
Time passesNo record kept
New subscriber connectsWaits for the next publish, sees nothing in the meantime

With retained messages

StepResult
Publisher publishes "online" with retainBroker stores the message
Time passesStored value persists
New subscriber connectsImmediately 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

  1. Enter your message in the publish area
  2. Check the Retain checkbox
  3. 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 immediately

The 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 users

Clearing 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:

FeaturePurpose
RetainStore last message for new subscribers
QoSDelivery 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

TopicWhy retain
Agent presence (online/offline)New subscribers see current presence
Latest state snapshotLast known value is meaningful on connect
Configuration valuesClients pick up config on subscribe
Current resource stateState is more useful than every change event

Don't retain

TopicWhy not
Events or logsHistorical, not current state
CommandsShould be transient
Chat messagesNot "last known value"
NotificationsOne-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 alert

CloudSignal 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:

PlanRetention period
Free7 days
Pro30 days
EnterpriseCustom

After the retention period, retained messages are automatically cleared.


Next steps

On this page