Start at the acknowledgement.

An AMQP delivery does not become durable because the consumer callback started. In the telemetry lab, ownership changes only after SQLite commits the event and the replay counters in one transaction. The worker then sends a manual acknowledgement.

If the process disappears after commit but before acknowledgement, the broker may send the same event again. That is expected recovery behaviour.

This gives the storage boundary a precise job: make the repeated event harmless. The envelope carries a stable event_id, and the telemetry table uses that value as its primary key. An INSERT OR IGNORE turns a redelivery into a recorded duplicate rather than a second observation.

Stable identity is different from sequence.

Sequence answers an ordering question. Identity answers a sameness question. Treating them as interchangeable causes trouble: two different observations can share a sequence after a device restart, while one event can be delivered twice with the same sequence.

The lab therefore keeps both. Identity protects idempotency. A replay-scoped cursor compares sequence numbers and marks a unique event as out of order when it arrives behind the highest value already stored.

event_id       PRIMARY KEY   -- is this the same event?
replay_id      TEXT          -- which experiment owns the cursor?
equipment_id   TEXT          -- which source produced it?
sequence       INTEGER       -- did it arrive behind prior evidence?
out_of_order   INTEGER       -- recorded, not silently discarded

A late event is still evidence. Whether it should update an operational state estimate is a separate domain decision; this storage lab deliberately does not pretend to answer it.

Failure paths should disagree on purpose.

Invalid envelope

Malformed JSON will not become valid after another delivery. The worker rejects it without requeue and logs the reason. A production system would normally add a dead-letter policy and an operational alert; the lab names that gap instead of hiding it.

SQL operation fails

A transient storage failure can recover. The worker negatively acknowledges with requeue. If the original transaction actually committed but the client lost the result, the stable identity still protects the retry.

Connection disappears

The RabbitMQ client can recover its connection and topology, but publication during a connection failure is not automatically buffered. The publisher therefore uses confirms and treats a failed publish as a failed operation rather than inventing success.

What the experiment proves.

The unit suite sends the same envelope twice and asserts one row, two deliveries and one duplicate. The integration suite crosses an actual RabbitMQ boundary with duplicates and reordered windows, then waits for SQL-owned counters.

It proves those behaviours for this implementation and test topology. It does not prove exactly-once delivery, distributed transactions, broker clustering, safety certification or fitness for an operational control system.