Call
Home>Blogs & Insights>Redis for Real-Time Systems: State, Pub/Sub, Streams, and Latency Design
Redis

Redis for Real-Time Systems: State, Pub/Sub, Streams, and Latency Design

A practical guide to Redis in real-time backends: hot state, TTLs, sorted sets, geospatial indexes, Pub/Sub, Streams, reconnect recovery, backpressure, hot keys, and latency-sensitive production design.

June 25, 2024
10 min read
0 views
Lofingo Team
Redis for Real-Time Systems: State, Pub/Sub, Streams, and Latency Design

Redis for Real-Time Systems: State, Pub/Sub, Streams, and Latency Design

Redis is a strong building block for applications that must react quickly to changing state: dashboards, multiplayer state, presence, live counters, location updates, alerts, collaborative features, and event-driven backends.

But “real-time” is too broad to be one Redis pattern.

You first need to decide whether the system is moving current state, ephemeral signals, or durable events. Redis has different primitives for each.

> In this article, “real-time” means low-latency interactive/event-driven applications—not hard real-time systems with formally guaranteed deadlines.

Start with the semantics, not the command

A useful mapping is:

RequirementRedis primitive
Latest value / hot stateStrings, hashes, JSON
Atomic countersStrings with INCR/related commands
Expiring temporary stateTTLs
Ranked/ordered live stateSorted sets
Nearby-location queriesGeospatial indexes
Ephemeral live broadcastPub/Sub
Retained ordered eventsStreams
Timestamped metricsTime series, where appropriate

The Redis data type documentation is valuable because Redis is not simply a key-value cache. Its native structures let the server perform operations that would otherwise require more application-side coordination.

A reference real-time architecture

A typical application may combine several Redis roles:

Rendering diagram…
Diagram generated from the article's Mermaid source.

Here Redis is not one monolithic “real-time database.” It is serving several carefully separated paths:

  • current hot state;
  • cross-node live fan-out;
  • retained event processing;
  • temporary coordination.

That separation makes failure behavior much easier to reason about.

Pattern 1: Keep frequently changing hot state in Redis

Some real-time features care primarily about the latest state, not every historical transition.

Examples:

current game score
active session metadata
latest device state
online/presence lease
live dashboard counter
current worker heartbeat

A hash can group fields:

HSET match:8172 \
  home_score 2 \
  away_score 1 \
  phase second_half

A counter can be updated atomically:

INCR dashboard:orders_today

This works well when request handlers know the exact keys they need and the working set benefits from in-memory access.

Do not turn Redis into an unbounded history store merely because the latest value lives there efficiently.

Pattern 2: Use TTLs for state that should disappear

Real-time systems contain lots of state whose natural lifecycle is “valid only while refreshed.”

Examples:

  • presence;
  • heartbeats;
  • temporary locks/leases;
  • typing indicators;
  • short-lived deduplication keys;
  • rate-limit windows;
  • transient session state.

For example:

SET worker:42:heartbeat alive EX 30

If the worker stops refreshing the key, the state expires automatically.

This is usually safer than depending on a graceful “offline” event that may never arrive after a crash or network loss.

The TTL duration still defines semantics. A 30-second expiry does not mean the worker is known to be alive for 30 seconds—it means the application is willing to consider that heartbeat fresh for that long.

Pattern 3: Use sorted sets for ordered live state

Redis sorted sets store unique members ordered by a score.

That maps naturally to continuously changing rankings and time/priority indexes.

For a leaderboard:

ZADD leaderboard:weekly 1450 player:42
ZADD leaderboard:weekly 1510 player:77
ZRANGE leaderboard:weekly 0 9 REV WITHSCORES

The official sorted-set documentation lists leaderboards and sliding-window rate limiting among common uses.

Other useful real-time patterns include:

member = scheduled job ID, score = execute_at
member = session ID, score = last_activity timestamp
member = item ID, score = live ranking value

Sorted sets are excellent when the application needs current order by score. They are not a replacement for event history.

Pattern 4: Use geospatial indexes for changing location state

Redis geospatial indexes can associate members with longitude/latitude coordinates and answer location-based queries.

For example:

GEOADD drivers:agra 78.0081 27.1767 driver:42

The Redis geospatial documentation covers commands for storing positions, calculating distance, and finding members around a location.

A common architecture keeps only the latest operational location in the low-latency index while shipping long-term location history elsewhere if the product actually needs it.

Do not continuously retain every historical coordinate in the same hot structure unless that is intentionally the data model.

Pattern 5: Pub/Sub for events that are useful right now

Redis Pub/Sub is a low-latency broadcast mechanism.

For example:

PUBLISH dashboard:orders '{"type":"order.updated","id":"8172"}'

Every currently subscribed process receives the event.

This is useful for:

  • live UI invalidation;
  • presence signals;
  • typing indicators;
  • cross-node WebSocket fan-out;
  • cache invalidation;
  • best-effort operational events.

But the Redis Pub/Sub documentation defines Pub/Sub as at-most-once. An offline subscriber misses the message permanently.

That gives you a simple test:

> If a consumer can recover by reading current authoritative state, Pub/Sub may be enough.

If missing an event permanently breaks correctness, use a retained mechanism.

Pattern 6: Streams for events consumers must catch up on

Redis Streams store ordered entries and support retained history, consumer groups, acknowledgments, pending entries, and replay.

Producer:

XADD events:orders * type order.updated order_id 8172

Backend consumers can then process the event at their own pace.

The Redis Streams documentation describes Streams as an append-only log with several consumption strategies, including consumer groups.

Streams are a better fit than Pub/Sub for:

  • asynchronous workflows;
  • projections/read-model updates;
  • consumers that can be temporarily offline;
  • replayable integration events;
  • retained telemetry/event feeds;
  • processing where acknowledgments matter.

They still need a retention policy. A stream that grows forever eventually becomes a memory/capacity problem.

Pub/Sub and Streams solve different failures

A simple comparison:

Pub/Sub:
producer -> connected consumers
           offline consumer misses event

Streams:
producer -> retained stream -> consumers
                         \-> consumer can catch up/replay

Do not use Streams everywhere merely because they are more durable. Persistence, pending tracking, consumer-group state, and retention add complexity that a disposable typing indicator does not need.

Likewise, do not use Pub/Sub for an event that is the only trigger for a critical business action.

Separate “state changed” from the state itself

One of the cleanest real-time patterns is to make live events hints to read authoritative state.

For example:

1. update durable order state
2. update/rebuild hot Redis state if needed
3. publish {type: order.updated, id: 8172}
4. client/service receives signal
5. reader fetches canonical current state

This minimizes giant live payloads and gives reconnecting clients a recovery path.

For workflows where every transition must be processed, use a durable event pipeline instead of relying only on a “state changed” hint.

Reconnection is part of real-time design

A real-time connection is temporary by definition.

Browsers sleep, Wi-Fi changes, mobile apps background, servers deploy, and load balancers terminate idle connections.

A robust client protocol should know how to recover:

reconnect
-> authenticate
-> provide last durable cursor/version
-> fetch missed/current state
-> restore subscriptions
-> resume live delivery

The live channel should make the experience fast. Durable state or retained events should make it recoverable.

Backpressure does not disappear because Redis is fast

If producers create updates faster than consumers can process them, you have backpressure somewhere in the system.

It may appear as:

  • growing Redis Stream lag;
  • growing worker pending counts;
  • expanding gateway socket buffers;
  • rising process memory;
  • overloaded downstream databases;
  • clients receiving obsolete intermediate states.

For replaceable state updates, coalescing can be better than queueing every transition.

Example:

stock widget receives values 101, 102, 103, 104
slow UI may only need latest = 104

For non-replaceable durable events, dropping is not acceptable; the consumer must either catch up or the producer pipeline must apply flow control/capacity limits.

The right policy depends on whether you are moving state or events.

Latency design is more than putting data in memory

Redis is designed for low-latency operations, but one slow operation can still hurt a real-time workload.

The official Redis latency guide explains that command execution is mostly served sequentially. Expensive operations can therefore delay other clients.

Practical rules:

  • avoid KEYS in normal production request paths;
  • understand command complexity before using it on huge collections;
  • use incremental scan commands for administrative iteration;
  • keep Lua/scripts/functions short because execution is atomic and blocks other command execution while running;
  • watch the Slow Log and latency monitoring;
  • bound collection sizes where possible;
  • avoid huge values that create network and processing spikes;
  • measure p95/p99 application latency, not only average Redis command time.

The Redis programmability documentation specifically warns that slow scripts block other clients while they execute.

Hot keys can break an otherwise distributed design

A real-time system often has uneven traffic.

Examples:

one viral livestream
one giant chat room
one global leaderboard
one popular product event
one tenant with most traffic

Even a Redis Cluster cannot magically distribute one key across every shard. A single hot key belongs to one hash slot and therefore one primary shard.

Possible responses depend on the data model:

  • partition by room/tenant/entity;
  • split replaceable counters into sharded counters and aggregate;
  • use local fan-out after one Redis event;
  • isolate exceptional workloads;
  • avoid hash tags that collapse unrelated traffic onto one slot;
  • redesign the feature if the access pattern fundamentally requires one global mutable object.

Horizontal scaling works best when the keyspace itself can distribute.

“Real-time” does not mean “durable”

Low latency and durability are separate properties.

A Pub/Sub message can be extremely fast and still be lost for an offline subscriber.

A Redis key can be served from memory and still require deliberate persistence, replication, backup, and recovery planning if it contains important state.

A Stream can retain events and still need idempotent consumers because delivery/recovery can cause duplicate processing.

For every piece of state, document:

source of truth
acceptable data loss
replay/recovery method
expiry/retention
consistency requirement
ownership

Without that, “Redis makes it real-time” is an implementation detail, not an architecture.

Observability for real-time Redis workloads

Monitor the user-visible pipeline, not only Redis CPU.

Useful signals include:

  • Redis command latency and latency spikes;
  • slow commands;
  • memory usage and evictions;
  • Pub/Sub message volume;
  • Stream length, lag, and pending entries;
  • reconnect rate;
  • WebSocket outbound queue depth;
  • dropped/coalesced ephemeral updates;
  • hot-key traffic concentration;
  • backend consumer throughput;
  • end-to-end event-to-client latency.

Redis' latency monitoring framework can help diagnose server-side latency events, but you still need application-level metrics to know whether users are receiving updates on time.

When Redis is not enough

Redis may not be the right primary platform when you need:

  • months or years of large event retention;
  • complex event-time windows and stateful stream processing;
  • massive analytical scans over event history;
  • strict hard-real-time deadline guarantees;
  • a dataset far larger than the hot in-memory working set with little benefit from Redis semantics;
  • broker features/routing guarantees that would require substantial custom logic.

Use the right combination of durable databases, streaming platforms, analytics systems, and edge protocols rather than forcing every real-time requirement into one datastore.

Production checklist

Before shipping a Redis-backed real-time feature, verify:

  • the state/event delivery semantics are explicit;
  • Pub/Sub is used only where at-most-once delivery is acceptable;
  • Streams have bounded retention and recoverable consumers;
  • important current state has a source-of-truth/recovery plan;
  • transient presence/leases expire automatically;
  • reconnecting clients can reconcile missed state/events;
  • slow consumers cannot grow memory without bounds;
  • large/slow Redis commands are kept off latency-sensitive paths;
  • hot keys and giant fan-out topics are measured;
  • persistence/HA requirements match the importance of Redis-held state;
  • end-to-end latency is monitored, not only Redis latency;
  • a dedicated streaming/analytics system is used when the workload outgrows Redis' role.

The main takeaway

Redis helps real-time systems because it offers several low-latency primitives—not because every real-time problem should use the same one.

Use normal data structures for current hot state, TTLs for temporary state, Pub/Sub for disposable live signals, and Streams for retained events that consumers must catch up on. Then design recovery, backpressure, hot-key behavior, and latency limits around those semantics.

That is what turns Redis from a fast component into a predictable real-time architecture.

Tags:RedisReal-Time SystemsPub/SubRedis StreamsLow LatencyEvent-Driven Architecture
Lofingo Team
Written by

Lofingo Team

Official writer and content strategist at Lofingo. Dedicated to delivering high-quality insights on technology and market trends.

Share your thoughts:

Discussion (0)

No comments yet. Be the first to start the discussion!