Articles
MQTT Interview Questions: QoS, Retained Messages, and Persistent Sessions
Practice MQTT interview questions with QoS traces, retained-message boundaries, persistent sessions, reconnect decisions, and duplicate-safe business effects.
An MQTT interview often becomes difficult at the moment a device reconnects. The broker accepted a message, the acknowledgment disappeared, and somebody asks whether the application can safely charge the customer. Reciting “QoS 2 means exactly once” does not answer that question.
The useful distinction is between four contracts: delivery handshake, latest topic value, client session, and business effect. This guide uses original packet traces and reconnect exercises to keep those contracts separate. Protocol statements are grounded in the MQTT specifications; the devices, numbers, and failure scenarios are practice fixtures, not reported interview questions or production measurements.
Your goal is to explain what survives failure and what evidence would prove it.
What do MQTT QoS levels actually guarantee?
MQTT defines QoS 0, 1, and 2 for delivery between protocol peers. Their exchanges are respectively a PUBLISH without an acknowledgment handshake, PUBLISH/PUBACK, and PUBLISH/PUBREC/PUBREL/PUBCOMP. Delivery to a subscriber is a separate exchange from delivery to the broker. State the hop before stating its guarantee. See the MQTT 3.1.1 specification, sections 4.3 and 4.6.
An interview answer should attach those mechanics to a requirement. A frequently refreshed temperature sample may tolerate a lost sample. A safety alarm may need acknowledgment and durable application handling. A payment command needs a business identity and transaction boundary regardless of which QoS level carries it.
Ask what the receiver does after accepting the packet. Does it update memory, write a database row, or call another service? Those are different failure surfaces. An acknowledgment proves completion of a protocol step, not that every downstream action achieved the intended business outcome.
| Interview prompt | Answer boundary | Follow-up to ask |
|---|---|---|
| Why choose QoS 0? | Acceptable loss with lower delivery overhead | Can the next sample replace the missing information? |
| Why choose QoS 1? | Acknowledged delivery with duplicates possible | Where is duplicate processing suppressed? |
| Why choose QoS 2? | More protocol state to avoid duplicate delivery within that exchange | What happens beyond the MQTT receiver? |
| Publisher uses QoS 2; subscriber requests QoS 0 | Do not assume one end-to-end QoS 2 contract | What delivery level did the subscription actually obtain? |
Avoid claiming that the highest level is automatically best. Describe the cost you would measure: bytes, extra exchanges, outstanding state, reconnect behavior, and application latency under loss. A label alone gives none of those measurements.
Trace a lost acknowledgment without confusing delivery and processing
Consider a synthetic vending-device command with business ID purchase-42. The publisher uses QoS 1. The following trace concerns the publisher-to-broker hop; a subscriber’s delivery has its own packet identifier and acknowledgments.
| Step | Observation | What remains uncertain |
|---|---|---|
| 1 | Publisher sends PUBLISH, packet identifier 17, event purchase-42 | Whether the broker has accepted it |
| 2 | Broker accepts the publication and sends PUBACK | Whether the publisher received PUBACK |
| 3 | Connection fails before the publisher receives it | Sender still has an unfinished exchange |
| 4 | Client resumes the existing session and retransmits the outstanding publication | The business event may already have reached a consumer |
| 5 | Consumer sees purchase-42 again | Whether its earlier database transaction committed |
In MQTT 5, reconnecting with an existing session is the specified occasion for retrying unacknowledged QoS publications or PUBREL; do not invent a universal periodic retransmission timer while the connection remains established. The reconnect rules are in MQTT 5, section 4.4.
Now place the failure at the consumer. Suppose it writes a sale, crashes before recording “processed,” then receives the same event again. A separate deduplication flag written afterward cannot close that gap. A defensible design makes the event marker and local business mutation atomic, with a unique business key.
begin transaction
insert processed_event(device_id, event_id)
under a unique constraint
if insertion succeeded:
insert sale(device_id, event_id, amount)
commit
This is application pseudocode, not an MQTT API. If the marker already exists, verify that the stored event corresponds to the same operation rather than silently accepting a reused ID with a different amount. A packet identifier is unsuitable as a permanent business key: it identifies a protocol exchange, not a globally unique purchase forever.
If charging an external payment service cannot participate in the same database transaction, the answer must change. Use a downstream idempotency key, an outbox, and reconciliation appropriate to that service. Do not promise that one local transaction atomically commits an unrelated remote side effect.
Is a retained message an offline message queue?
No. Retention represents the topic’s latest retained publication for a later subscriber, not an archive of every missed event. MQTT 3.1.1 specifies retained delivery on subscription and deletion by a retained publication with a zero-length payload. Those rules are documented in section 3.3.1.3.
Work through two topics. A sensor publishes retained values 18, 19, and 21 to plant/7/temperature. A new subscriber should think “current snapshot,” not “three historical readings.” If the topic instead represents alarm events, replacing the retained value loses the narrative of earlier alarms. Store that history elsewhere when the requirement needs it.
A persistent subscriber session addresses a different question: what eligible messages accumulated for an already established subscription while its client was disconnected? A retained snapshot may be useful even when that subscriber never existed. An offline queue belongs to client session state and depends on the subscription, delivery level, expiry rules, and broker limits.
A practical topic-design answer can use both concepts without treating them as substitutes. Publish the current machine state as a retained snapshot; publish immutable transitions on an event topic. Put a timestamp and sequence or version in the snapshot so a dashboard can detect stale information. Decide separately whether disconnected clients need a backlog of transitions.
Do not use retention as proof that a device is currently alive. A stored “online” value can outlive the process that wrote it. A presence design needs explicit failure handling and freshness interpretation; a retained flag by itself is insufficient evidence.
Which settings preserve a session after reconnect?
Distinguish protocol versions before answering. MQTT 3.1.1 uses Clean Session. MQTT 5 separates Clean Start from Session Expiry Interval: starting clean discards the prior session, while expiry governs how long the session can remain after disconnection. In MQTT 5, omitting Session Expiry Interval gives an expiry interval of zero. Retained messages are not part of that session. See MQTT 5, CONNECT properties and section 4.1.
For an original reconnect drill, assume a stable client ID, an established subscription, a broker that honors a 60-second session expiry, and no overriding limits. Disconnect at time zero. A reconnect after 45 seconds without a clean start can resume the session if it still exists. After 75 seconds, expect the old session to have expired; inspect the broker’s Session Present response rather than pretending the setting proves survival.
Ask the candidate to change one assumption at a time. What if the software generates a new client ID on every boot? What if deployment changes Clean Start? What if two devices accidentally use the same identity? These are configuration and identity problems that selecting QoS 2 does not resolve.
Separate session expiry from message usefulness. A ten-minute session could contain an operational command that is unsafe after thirty seconds. Define business expiration even if protocol or broker configuration also expires messages. “It was eventually delivered” is not a successful outcome when the command’s valid window has passed.
How do you investigate messages missing after a reconnect?
Start with a narrow incident statement: which client, topic, event ID, interval, and expected message count? Collect connection flags, client identity, Session Present, subscription acknowledgments, publication metadata, and broker queue evidence. A screenshot showing “connected” does not prove the right subscription was restored.
Use a hypothesis ladder. First prove that the publication entered the broker. Then prove that an eligible subscription existed. Then examine whether its session survived. Finally inspect queue limits, expiry, subscriber delivery, and application handling. The ladder prevents an application rejection from being mislabeled as broker loss.
Broker restart adds another boundary. MQTT session semantics are not a blanket guarantee that every broker configuration survives process or disk failure. For example, Mosquitto’s configuration reference documents persistence and queue settings. Read the deployed broker version and actual configuration before claiming restart durability.
An incident exercise can give you three independent observations: Session Present is false, the client ID changed during upgrade, and retained temperature still arrives. The simplest supported conclusion is not “persistent sessions work because we received a value.” The retained value and old session are separate stores; the new identity explains why that client did not resume the old subscription state.
Report what is known and what remains unproved. If you cannot inspect persistence configuration or queue counters, say that those are next checks. Do not fill the gap with a claim that the protocol mandates the operator’s storage policy.
Build a small failure matrix before choosing a design
For a practice lab, define observable assertions rather than only publishing a happy-path message. Record business-event counts separately from packet counts. A duplicate packet is not automatically a duplicate sale, and a single packet can still trigger buggy application work twice.
Test an ordinary connection, a lost acknowledgment, a reconnect before expiry, a reconnect after expiry, and a broker restart under the documented persistence setting. Add a new subscriber to demonstrate retained delivery. Clear the retained value and verify that the old snapshot is no longer delivered to a fresh subscriber.
Include a capacity case: a disconnected client receives more eligible events than the configured queue permits. State the expected behavior from that broker’s documented settings, then measure it in a disposable environment. “Persistent” should never be translated into “unbounded storage.”
Your acceptance record should include configuration, protocol version, client IDs, event IDs, timing assumptions, and expected application effects. If the result differs, preserve the packet trace and broker logs. Changing several flags until the test passes makes the explanation less useful than a reproducible failure.
Sources and Further Reading
- OASIS MQTT 5 specification: reconnect, session expiry, and protocol state.
- OASIS MQTT 3.1.1 specification: delivery handshakes and retained-message behavior.
- Mosquitto configuration manual: implementation-specific persistence and resource limits.