Skip to content

Compress large replay-buffer entries (opt-in) - #20

Open
rjmackay wants to merge 1 commit into
mainfrom
valkey-replay-compression
Open

rjmackay wants to merge 1 commit into
mainfrom
valkey-replay-compression

Conversation

@rjmackay

Copy link
Copy Markdown

:claude:

What

Opt-in gzip compression for the SSE replay buffer (the per-run Redis List in redis_broker.py).

  • New setting REDIS_REPLAY_COMPRESSION (default false).
  • When on, replay-buffer entries ≥ 1 KiB are stored as gz: + base64(gzip(json)). Below the threshold, or when off, entries stay plain JSON.
  • Reads are self-describing: _decompress decodes an entry by its gz: marker, not the flag, so a reader on this version handles both compressed and plain entries.
  • Only the stored List is compressed; the live PUBLISH payload is left plain (transient, no memory cost).

Why

The replay buffer RPUSHes every streamed event — including full values state snapshots (the default stream mode) — unslimmed, capped only by count (10k) and TTL (600s). On a large graph state it's the dominant Redis-memory consumer. That JSON compresses several-fold, so this is the biggest single lever on broker memory.

Rollout (order matters)

Older instances can't decode gz: entries, so this must roll out reads-before-writes:

  1. Merge + deploy this everywhere with the flag off — all instances can now read compressed entries.
  2. Then set REDIS_REPLAY_COMPRESSION=true to start writing compressed.

Merging with the default keeps it a no-op, so it's safe to land ahead of the flip.

Tests

Added TestReplayCompression in test_redis_broker.py: round-trip + genuine shrink, disabled/below-threshold passthrough, plain-JSON passthrough (the back-compat guarantee), replay() decoding compressed entries, and put() compressing the stored entry while leaving PUBLISH plain. make test-api green (54 passed, incl. all pre-existing), ruff clean.

🤖 Generated with Claude Code

The SSE replay buffer RPUSHes every streamed event to a per-run Redis
List, including full "values" state snapshots, unslimmed and capped only
by count (10k) and TTL (600s). On a large graph state that List is the
dominant broker-memory consumer. Gzip entries over 1 KiB before storing
them (base64-wrapped, since the client runs decode_responses=True),
typically shrinking that JSON several-fold.

Off by default (REDIS_REPLAY_COMPRESSION). Entries are self-describing
via a "gz:" marker, so a reader decodes both formats regardless of the
flag — deploy everywhere first, then flip the flag on. Only the stored
List is compressed; the transient PUBLISH payload is untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ChrisXuzhou
ChrisXuzhou marked this pull request as ready for review September 17, 2026 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant