Summary
Room streams are only ever trimmed by the compaction task. For rooms used purely for awareness/presence (we run one per workspace: every authenticated tab connects and publishes presence), that trimming coupling has a failure mode: anything that stops compaction for the room — a lost task, a worker outage, an operator quarantine — leaves a stream that grows without bound while the server keeps accepting presence writes.
Production incident: one awareness room whose compaction had been disabled accumulated 1.56M messages / 844 MB — 75% of that environment's entire Redis — at ~2.7 msg/s, in 8 days.
What we run in production (offered as a PR)
redis.awarenessStreamMaxLen?: number — an approximate XADD MAXLEN ~ cap applied only to awareness rooms at write time, so Redis bounds the stream itself, independent of compaction, workers, and quarantines. Sized by retention (at our busiest observed room, 33 msg/s, a 10k cap ≈ 5 minutes — far above the 60s message lifetime and the ~30s awareness re-broadcast cadence). Document rooms are never capped: their un-compacted tail is real data.
addMessage rejects non-awareness messages to awareness rooms — the cap evicts by position, not type, so a document update stored there could be evicted before compaction persists it; better to refuse a write whose durability cannot be honored.
disableCompaction refuses awareness rooms (returns false): disabling compaction there removes the only trimmer while writes keep arriving, and there is nothing to recover in exchange.
The general shape this points at: rooms declarable as ephemeral (no persistence, server-owned bounded stream) would serve presence, notifications, and similar high-frequency transient channels first-class — today they masquerade as documents.
Summary
Room streams are only ever trimmed by the compaction task. For rooms used purely for awareness/presence (we run one per workspace: every authenticated tab connects and publishes presence), that trimming coupling has a failure mode: anything that stops compaction for the room — a lost task, a worker outage, an operator quarantine — leaves a stream that grows without bound while the server keeps accepting presence writes.
Production incident: one awareness room whose compaction had been disabled accumulated 1.56M messages / 844 MB — 75% of that environment's entire Redis — at ~2.7 msg/s, in 8 days.
What we run in production (offered as a PR)
redis.awarenessStreamMaxLen?: number— an approximateXADD MAXLEN ~cap applied only to awareness rooms at write time, so Redis bounds the stream itself, independent of compaction, workers, and quarantines. Sized by retention (at our busiest observed room, 33 msg/s, a 10k cap ≈ 5 minutes — far above the 60s message lifetime and the ~30s awareness re-broadcast cadence). Document rooms are never capped: their un-compacted tail is real data.addMessagerejects non-awareness messages to awareness rooms — the cap evicts by position, not type, so a document update stored there could be evicted before compaction persists it; better to refuse a write whose durability cannot be honored.disableCompactionrefuses awareness rooms (returnsfalse): disabling compaction there removes the only trimmer while writes keep arriving, and there is nothing to recover in exchange.The general shape this points at: rooms declarable as ephemeral (no persistence, server-owned bounded stream) would serve presence, notifications, and similar high-frequency transient channels first-class — today they masquerade as documents.