Skip to main content

When MQTT outruns the destination

Incoming MQTT can outpace a database insert, a cloud bridge, or a PLC write. ADD ROUTE_CONFIG lets each route choose whether to wait or to drop the newest message — without crowding out every other route.
Like a ticket window with a limited line. People already being served always finish. When the line is full you can wait for a spot, wait a short time then turn the newest arrival away, or turn them away immediately.

When to use it

  • Leave the default (balanced) on most routes.
  • Use lossless when a path must not lose messages (audit, compliance) and you accept that the publisher may wait.
  • Use realtime when high-rate telemetry must never stall the client that published it.
  • Set OVERLOAD_CAPACITY to cap one noisy route so it cannot crowd out others.
ADD ROUTE_CONFIG is the only LoT block that works on every route type. Place it next to that type’s own config (SQL_CONFIG, SOURCE_CONFIG, MODBUS_CONFIG, and so on). Order among ADD blocks does not matter.
Let’s look at how to set it, starting with the three common contracts.

Quick Start

Use lossless on a forwarding path that must keep every message. The publisher waits until this route has room — it never drops.

Settings

All three settings are optional. An absent ADD ROUTE_CONFIG block inherits the broker default entirely.
A message already accepted for a route is never evicted. Only the arriving message can be dropped. That keeps sequences such as Sparkplug birth then data self-consistent under load.
Do not set OVERLOAD_CAPACITY together with OVERLOAD_POLICY "lossless". A capacity cap drops overflow; lossless never drops. The broker logs an error naming the route, ignores the capacity, and runs the route as lossless. The same conflict applies if the route inherits lossless from the broker default and then declares a capacity.

Defaults

Each setting resolves on its own:
  1. No ADD ROUTE_CONFIG block — the route inherits the broker default for policy, timeout, and capacity.
  2. A block is present but a setting is omitted — that setting does not copy the broker’s timeout or capacity. OVERLOAD_POLICY inherits the broker default. OVERLOAD_TIMEOUT and OVERLOAD_CAPACITY use that policy’s own default (50 ms for balanced, unbounded capacity).
  3. An invalid value (unknown policy name, negative timeout, non-positive capacity) does not stop the route loading. The broker logs an error and uses that field’s default.
Broker-wide defaults are environment variables, read once at process start. Change them and restart the broker. A route’s own ADD ROUTE_CONFIG always overrides these for that route. OVERLOAD_CAPACITY on a route is a private budget for that route. The shared ceiling is separate: one route can hit its own cap and start dropping while other routes still have room. See Broker Configuration for how these sit alongside other broker limits.

What happens under load

When a route is waiting, that wait can delay the publishing client’s own publish — only that client, and only up to the wait budget. Other connected clients are not stalled by this route. The broker logs two different saturation conditions (each at most once every five seconds):
  • The shared route queue is full — every route waiting behind it is affected.
  • A single route is over the OVERLOAD_CAPACITY it declared for itself — the shared queue may still have room.
If two routes could match the same topic (for example one exact mapping and another sensors/#), the broker applies the stricter wait-or-drop choice among those candidates. A lossless route on an overlapping pattern can make a realtime route wait, even if only the realtime route would have handled the message. The broker never drops a message because a more lenient route asked to drop it. If mixed policies on overlapping wildcards wait or drop more than you expect, check the patterns first — that behavior is by design.

Troubleshooting

That route’s own OVERLOAD_CAPACITY is exhausted. Look for the broker warning that a route is over its in-flight budget, not the warning that the shared queue is full.
Working as designed — lossless waits until there is room. Switch to balanced with a timeout if you would rather drop than stall, or cap a noisy route with OVERLOAD_CAPACITY so it drops its own overflow instead.
It is declared alongside OVERLOAD_POLICY "lossless" (or the broker default is lossless). Check the broker log for the lossless/capacity conflict — capacity is ignored, not applied.
Another route’s overlapping wildcard pattern resolved a stricter policy for that topic. See the overlapping-pattern warning above.
The resolved policy is realtime. That is expected — realtime drops without waiting.

Best practices

  • Start with the default balanced policy. Change a route only when you have a reason (must not lose, must not stall, or must not crowd others).
  • Use lossless sparingly. It protects delivery at the cost of delaying the publisher that caused the backlog.
  • Put OVERLOAD_CAPACITY on the noisy route, not on the critical one — the critical route can stay unbounded while the noisy route drops its own overflow.
  • Prefer exact topic mappings when two routes would otherwise share a broad + / # pattern with different policies.
  • Invalid settings never fail the route silently: read the broker log after deploy if behavior does not match the block you wrote.

Next Steps

Routes Overview

Define routes, mappings, and status topics.

Broker Configuration

Set broker-wide route overload defaults and other limits.
Last modified on August 28, 2026