Concepts
Retention
Age-based retention advances the trim watermark for you; history goes logically at once and physically later; deleting a stream
A per-stream trim watermark bounds history in nova: everything below it is gone the moment the watermark moves, and the auditor reclaims the bytes later. This page covers age-based retention, what "gone" means for readers and for your bill, and stream deletion; the watermark's explicit form is the Trim verb.
Age-based retention
A stream's retention_max_age_ms (set at creation or copied from the
bucket's defaults, and changeable at any time with ReconfigureStream
— including back to unbounded) arms a background retention duty that resolves
now − max_age against record time, advances the watermark to the first
record younger than that, reclaims what fell below, and re-arms itself for
the next expiry. Granularity is seconds, independent of any object
boundary: a quiet stream trims on time exactly like a busy one.
Retention reads record time as wall clock. That is why a stream cannot
combine age retention with uncapped timestamping (an application-scale
stamp would mis-trim silently), and nova refuses the combination at
create and update, on streams and bucket defaults alike. Client-supplied stamps
under the default client-prefer rule are capped at arrival time, so they
are safe with age retention.
nova stream create --bucket logs --key api --retention-max-age 168h
curl -s -X POST localhost:8080/v1/streams/logs/api -d '{"retention_max_age_ms":604800000}'Age retention trims through the leader like an explicit trim, so the leader's watermark stays exact. A stream with no age bound keeps history until you trim it.
retention_max_bytes exists on the wire and in bucket defaults but the
retention duty acts on age; do not rely on a byte bound to reclaim
history today.
What "gone" means
Deletion is two things at two speeds:
- Logically, at once. The watermark is a metadata write; from that instant no reader can see the records below it.
- Physically, later. The auditor reclaims settled objects that lie
wholly below the watermark. Because a stream's settled objects are
contiguous by sequence number, reclamation drops whole front objects
as the watermark passes them; at most one boundary object straddles.
Every reclaim waits out the read grace (
--auditor-read-grace, default 10 m) between an object's last reference dying and its physical delete, so a reader mid-fetch is never cut off. Transit bundles shared with other streams are reaped once every stream's extents in them are dead.
For cost, that means history you keep costs object-storage prices for as long as you keep it, and history you trim stops costing once the auditor has reclaimed it: minutes, not instantly, and longer when the auditor is behind. Backlog age is the signal to watch; the duties and their tuning are in auditor duties.
Deleting a stream
DeleteStream removes the stream itself. Nova routes it to the stream's
leader, which fences the stream, drains its writers, and tombstones the
record; on return the stream is gone for every caller (appends, reads,
and subscriptions fail with not-found) while physical reclamation runs
asynchronously. Deleting is idempotent: deleting an already deleted
stream succeeds; deleting one that never existed is not-found.
A stream recreated at the same (bucket, key) afterwards is a new
stream with a fresh ID and an empty history; nothing of the old one is
visible through the new address.
err := c.DeleteStream(ctx, addr)nova stream delete nova://demo/events
curl -s -X DELETE localhost:8080/v1/streams/demo/eventsA bucket can be deleted only when no streams live in it.
Source documents
docs/adr/0002-trim-watermark-retention.mddocs/design/000-decisions.mdproto/nova/v1/dataplane.protoclient/client.go