SCUA

News

SCUA 0.16.0 is out

August 19, 2026

This release is about making clusters something you can rely on under real conditions, and it comes out of running one properly rather than reasoning about it.

#Clusters, put under real faults

A SCUA cluster is a set of nodes sharing configuration state, and the hard part was never the happy path. It is what happens when a node restarts mid-write, when one has been offline long enough to hold a stale copy, when a peer's clock has drifted, or when the whole thing is under enough load that connections come and go while messages are in flight.

So we ran a real five node mesh in Docker and injected faults at it: killed nodes, partitioned them, rolled them back, skewed their clocks, and left it running under load. Everything that mesh surfaced has been fixed, including one fix whose first version did not work, which the mesh also caught.

The result is a cluster that reclaims space predictably, keeps deletes deleted across restarts and rejoins, survives peers disappearing mid-message, and does not let one lagging node pin the whole cluster's cleanup behind it.

#You can see clock skew now

cluster.stats reports rejected_skew: the number of writes discarded because the sending node's clock was too far ahead of yours.

This was previously counted nowhere, which is the worst place for it to be counted. A node with a bad clock could have every write it sent dropped, indefinitely, and the only symptom was writes quietly not arriving. Now it is a number you can watch and alert on.

#Datetimes compare directly

if deadline < time.now() then …

<, <=, > and >= work on datetimes, ordered by instant, with the offset as a tie-break. No conversion to milliseconds first.

#Two things to know when you upgrade

Durable cluster snapshots have a new format. A 0.16 node reads a 0.15 snapshot fine. A 0.15 node handed a 0.16 snapshot starts empty rather than loading it, deliberately: the new field records which stale writes to refuse, and loading the file without it would silently drop that protection. Upgrade a cluster together, and a node that gets rolled back will refill from its peers.

sys.exit inside spawn now stops that task, rather than restarting it from the top. If you need a whole run to fail, return the outcome and exit from the top level, because the exit code is still local to the task.

The changelog has the full accounting.