Efficient JWT Revocation with Redis ZSET and Stream
Use Redis ZSET for current revocations and stream for events; capture stream tip before ZSET read to avoid race.
Implement WarmCache logic with tip capture and ZSET read, start consumer from tip.
Summary
The article tackles the challenge of revoking stateless JWTs in a high‑throughput system. It describes a two‑layer design: a Redis sorted set (revoked_access_tokens) stores current revocations with JTI as member and expiry as score, and a Redis stream (revoked_access_token_events) provides a live feed of revocation events. To avoid race conditions during pod startup, the pod first captures the stream tip, then reads the ZSET snapshot, and finally starts the stream consumer from the captured tip. This reverse order ensures that any revocation that arrives between the ZSET read and stream subscription is replayed, while existing revocations are loaded directly.
The article details the Go implementation of WarmCache, including capturing the tip, reading the ZSET with ZRangeByScore, populating a local map, and starting the consumer. It also explains the two races: missing events between tip and ZSET, and replaying old events if starting from 0-0. The solution mitigates both by capturing the tip first.
This approach guarantees that a pod’s local revocation map is accurate within a few seconds of startup and stays up‑to‑date with minimal latency.
Key changes
- revoked_access_tokens ZSET with JTI and expiry score
- revoked_access_token_events stream for live feed
- Capture stream tip before ZSET read to avoid race
- Reverse order: tip, ZSET, start consumer
- WarmCache logic in Go populates local map
- Handle race 1 (missed events) and race 2 (replay old events)
- Local revocation map updated via stream consumer
- TTL of 30s for JWT cache to limit staleness