Concepts
Trimming
Trim advances a monotonic watermark — sequence numbers survive, and reads below it fail at once
Trim is the explicit way history ends: a per-stream watermark that only advances. Everything below it is gone the moment it moves; the auditor reclaims the bytes later. The two speeds are on the retention page, which also covers the age-based way the watermark moves for you.
Trim advances a watermark
Trim names a point (a sequence number, or a time resolved to the first
record stamped at or after it) and advances the stream's trim watermark
to it. Records below the watermark are logically deleted.
The watermark is monotonic: it only ever moves forward. The point
applied is max(current, min(requested, tail)), so a trim behind the
current watermark is a no-op and a trim past the tail trims everything
retained so far. Trimming is instant and metadata-only; the stream's
leader serves it when one holds the stream (a non-holder redirects, and
the SDK follows), and it goes straight to committed state otherwise.
err := c.Trim(ctx, addr, 1000) // drop records 0…999
err = c.TrimFrom(ctx, addr, cutoffMs) // drop everything stamped before cutoffMsnova stream trim nova://demo/events --entry 1000
nova stream trim nova://demo/events --at 2026-08-01T00:00:00Z
curl -s -X POST localhost:8080/v1/streams/demo/events/trim -d '{"seq_num":1000}'
curl -s -X POST localhost:8080/v1/streams/demo/events/trim -d '{"timestamp_ms":1722470400000}'Trim is its own action in scoped tokens, never bundled with append or read: it is irreversible data loss, and a credential must be granted it explicitly.
Sequence numbers survive a trim
Trimming never renumbers. After trimming below 1000, record 1000 is still
record 1000, the tail is unchanged, and CheckTail still reports the same
next sequence number. A sequence number is a permanent name; a trim only
changes which names are readable.
CheckTail reports timestamp_ms: 0 when the whole history has been
trimmed away, because no committed record's time is known any more.
Reads below the watermark fail
A read or subscription that starts below the watermark fails as
OutOfRange (client.ErrTrimmed in Go, 410 Gone over HTTP), distinct
from the 400 of a malformed request so a client can tell the two apart.
A subscription that is trimmed under mid-life ends with the same error.
To read from "the earliest still retained" instead of erroring, pass
clamp: the start is pulled up to the watermark.
r, err := c.Read(ctx, addr, 0, 100, client.WithClamp())nova read does this by default when you give no --from.
Source documents
docs/adr/0002-trim-watermark-retention.mdproto/nova/v1/dataplane.protoclient/client.go