Practical MQTT patterns

A lightweight SQLite MQTT broker for edge systems

See when one MQTT broker and one SQLite database are a practical fit for durable messaging on a small edge machine.

An edge deployment often needs durable messaging without operating a broker, a stream platform, a cache, and a job queue as separate services. Sagüin is designed for the smaller boundary: one Go binary, one node, and either memory or SQLite storage for explicit durable channels.

It is not a clustered replacement for a distributed event platform. It is a practical option when one machine owns the workload and its limits are understood.

Why SQLite fits the edge

SQLite provides transactions and crash recovery in one local database file without a separate database server. That makes it attractive for gateways, industrial PCs, small ARM machines, and remote installations where operational simplicity matters as much as throughput.

With Sagüin, a SQLite provider can hold:

  • append-channel records and consumer positions;
  • latest values;
  • queued jobs, leases, attempts, and dead letters;
  • persistent MQTT session state when configured for it;
  • retained messages when configured for it.

The exact durability boundary depends on the configured provider and synchronization policy. “Uses SQLite” is not itself a complete durability claim.

Where one node is the right trade-off

A single-node broker can be a good fit when:

  • the broker runs beside the equipment producing the data;
  • upstream connectivity is intermittent;
  • thousands of connections are enough and millions are not required;
  • local recovery matters more than automatic failover;
  • an operator can monitor one process and one storage device;
  • data can later be forwarded to a central system.

The same design is a poor fit when the service requires transparent node failure, consensus, multi-region availability, or horizontal write scaling. Sagüin deliberately provides no clustering or automatic failover.

Memory and SQLite fail differently

The memory provider is useful for tests, demonstrations, and workloads whose state can disappear. With snapshots it can preserve configured state across a graceful stop, but that is not the same promise as a transactionally updated on-disk database through an unexpected crash.

The SQLite provider keeps durable state in its database. Its acknowledgement and recovery behaviour, transaction grouping, file limits, and backup rules are documented rather than implied. Operators should choose based on the failure they need to survive.

Keep the deployment bounded

Small systems become reliable by making limits explicit. Plan and monitor:

  • maximum provider and channel bytes;
  • record and time retention;
  • MQTT session expiry;
  • message size and client limits;
  • queue attempts and dead-letter growth;
  • free disk space and database backup procedures.

When a durable provider is full or cannot commit a record, the correct outcome is backpressure: refuse the publish instead of acknowledging a promise that storage did not keep.

A useful edge topology

A common shape is:

devices  →  local Sagüin broker  →  local consumers
                    │
                    └─ append history → upstream bridge when connected

Local subscribers continue to use MQTT. An append channel keeps bounded history while the uplink is unavailable. When connectivity returns, an upstream consumer resumes from its stored position. Latest channels hold current device state, while queue channels can coordinate local work.

Operate the storage as a database

Keep the database on reliable local storage, enforce a provider size bound, observe write and recovery errors, and test restoration before relying on a backup. Do not copy a live database using a method that ignores its journal or write-ahead log.

Read RFC 0004: Storage for the authoritative SQLite contract, including transactions, backups, file permissions, provider limits, and recovery. RFC 0005: Operations covers health and metrics, and the Raspberry Pi measurements provide a concrete reference point rather than a universal capacity promise.