Replayable event stream
Keep the history
Store each record once and keep an independent position for every durable consumer. Replay after an outage without filling a private queue per client.
iot/+/telemetry/#A lightweight MQTT broker for the edge
Sagüin adds a replayable event stream, latest-value state, and a durable work queue to ordinary MQTT topics, inside one Go binary.

The gap
A truck parks underground. A substation loses its cellular link. A vessel crosses open ocean. When they reconnect, a bounded session queue may already have overflowed.
That is not a protocol failure. MQTT is transport. But when telemetry becomes billing evidence, maintenance history, or a safety record, “the link dropped” is no longer an adequate retention policy.
The usual answer is a broker, database, stream, cache, and job queue. Sagüin is for the deployment where that is too much infrastructure for one small machine and the person operating it.
Three durable primitives
Configure a region of the MQTT topic space as a channel. Everything outside a channel remains ordinary live broadcast.
Replayable event stream
Store each record once and keep an independent position for every durable consumer. Replay after an outage without filling a private queue per client.
iot/+/telemetry/#Latest-value state
Keep one current value per topic, with its age and channel position. Subscribe normally or point-read one value when you need it.
iot/+/stateDurable work queue
Lease work to one consumer, acknowledge the application outcome, retry after a timeout, and move exhausted work to a dead-letter channel.
iot/+/work/+The one idea worth stealing
An offline session normally needs its own bounded copy of every message it missed. An append channel stores each record once, then stores one position per consumer.
A week offline and a minute offline both cost one position. If retention overtakes it, Sagüin refuses the read instead of serving a plausible but incomplete history.
Read the delivery semanticsPer-client copies
One shared log
appendOne rule shapes the broker
Sagüin never acknowledges a promise it cannot keep.
What Sagüin is not
The useful boundary of a system is part of the product. Sagüin does not hide its trade-offs behind broad claims.
No clustering, consensus, or automatic failover.
No claim of exactly-once processing. Workers must be idempotent.
Thousands of connections, not millions.
It is a broker with durable channels, not an application platform.
Memory and SQLite fail differently, and the docs say so.
Run it where you can watch it, and tell us what breaks.
If plain publish/subscribe and retained messages are enough, Sagüin adds machinery you do not need. It earns its place when the replayable log, state store, or work queue removes another system from the edge.

Inspect the claim
The repository publishes its RFCs, invariants, test harnesses, Raspberry Pi measurements, and runnable demos.
Get started
Build the broker, create a Python environment for the ordinary MQTT clients used by the examples, then run the guided tour.
v0.1.0-rc.1 is a release candidate. A code review is under way before v0.1.0. Download binaries from GitHub Releases, or run ghcr.io/ifnesi/saguin:0.1.0-rc.1. Early days: run it where you can watch it, and tell us what breaks.
git clone https://github.com/ifnesi/saguin.git
cd saguin
go build -o bin/saguin ./cmd/saguin
python3 -m venv .venv
. .venv/bin/activate
pip install -r examples/requirements.txt
make demoCompanions, not dependencies
Sagüin remains a broker speaking MQTT. The viewer and SDKs are separate projects, versioned and deployed independently.
Browse live topics, replay channels, inspect dead letters, publish messages, and see broker health from a separate web or terminal client.
Optional conveniences over Eclipse Paho. The wire remains standard MQTT; the SDK is not required.
The same channel operations for MQTT.js, with matching verbs across the Python and JavaScript clients.