Redis Keyspace Notifications for Reactive Architectures
AI generated
SET
TTL
Redis · Keyspace Notifications · Pub/Sub · Events
Redis keyspace notifications
for reacting to changes without polling

Redis keyspace notifications turn every write operation and every key expiry into a Pub/Sub event that any number of consumers can react to. Instead of running expensive polling against the dataset, an application subscribes to exactly the changes it cares about and builds reactive architectures without an additional message queue.

13 min read notify-keyspace-events · SUBSCRIBE · expired Redis 6.x · 7.x · redis-cli

1. What Redis keyspace notifications really are

Redis keyspace notifications use the existing Pub/Sub mechanism of Redis to publish every relevant operation on a key as a message on a special channel. When a key is set, deleted, changed, or expires, Redis can automatically send a message to all clients that have subscribed to the corresponding channel. That is the decisive difference from an application that periodically queries the dataset with GET or SCAN to detect changes.

The practical benefit is that Redis keyspace notifications make polling completely unnecessary for all use cases where a system needs to react to data changes promptly. Instead of asking every few seconds whether something has changed, Redis actively reports the change as soon as it occurs. This drastically reduces both the load on Redis itself and the latency between change and reaction, often from seconds down to milliseconds.

Important for understanding: keyspace notifications are disabled by default, because generating and publishing every change as an event creates measurable overhead. Only through explicit configuration via notify-keyspace-events does an administrator deliberately enable this feature for the event types that are actually needed.

2. Configuring notify-keyspace-events

The notify-keyspace-events parameter controls which event categories Redis publishes, through a compact string of flag letters. K enables keyspace events, named according to the __keyspace@db__:key scheme, E enables keyevent events, named according to the __keyevent@db__:event scheme. Without at least one of these two flags, no notifications are generated at all, regardless of which other event types are configured.

The remaining flags select concrete command categories: g for generic commands like DEL and EXPIRE, s for set commands, h for hash commands, z for sorted set commands, x for expired events, e for evicted events caused by memory pressure. The A flag is a shorthand for all classes except the very verbose m flag for key miss events. For the most common use case, reacting to expiring keys, the combination Ex is fully sufficient and generates minimal additional overhead.


# Enable keyevent notifications for expired keys only (minimal overhead)
redis-cli> CONFIG SET notify-keyspace-events Ex

redis-cli> CONFIG GET notify-keyspace-events
1) "notify-keyspace-events"
2) "Ex"

# Enable both keyspace and keyevent notifications for all generic and string events
redis-cli> CONFIG SET notify-keyspace-events KEAg
redis-cli> CONFIG SET notify-keyspace-events KEA$

# Persist the setting in redis.conf for it to survive a restart
# notify-keyspace-events Ex

3. Keyspace and keyevent channels in detail

Redis keyspace notifications potentially publish each event on two different channels simultaneously, depending on the enabled K and E flags. The keyspace channel __keyspace@0__:mykey delivers the name of the event, such as set or expired, as the message, while the keyevent channel __keyevent@0__:expired delivers the name of the affected key as the message. These two perspectives complement each other: the keyspace channel is suitable when a client is interested in a specific key and wants to know what happens to it, the keyevent channel is suitable when a client is interested in a specific event type, regardless of which key is affected.

In practice, the vast majority of use cases exclusively use keyevent channels, because you usually want to know which keys have expired, not whether a specific, previously known key has expired. Subscribing to __keyevent@0__:expired delivers exactly this information, the database number in the channel name allows handling notifications separately per logical Redis database, which is especially relevant in multi-tenant setups.

4. Subscribing to expired events

The most common use case for Redis keyspace notifications is reacting to expiring keys, which is why this section shows the complete flow. First, notify-keyspace-events is enabled with the Ex flag, then a client subscribes to the __keyevent@0__:expired channel via PSUBSCRIBE with a wildcard for the database number or via SUBSCRIBE for a specific database. As soon as any key in that database expires, whether through active or passive expiration, Redis sends a message with the key name to all subscribers.

A classic practical example: a shopping cart is stored as a Redis key with a TTL of 30 minutes. If this key expires without an order being completed, a subscriber can react to the expired event and automatically trigger a reminder email to the customer. Without keyspace notifications, the application would instead have to regularly scan all cart keys and check which ones are about to expire or have already expired, a considerably more expensive and less precise approach.


# Terminal 1: enable notifications and subscribe to expired events
redis-cli> CONFIG SET notify-keyspace-events Ex
OK
redis-cli> SUBSCRIBE __keyevent@0__:expired
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__keyevent@0__:expired"
3) (integer) 1

# Terminal 2: create a cart key with a short TTL
redis-cli> SET cart:user:4711 "..." EX 5
OK

# Back in Terminal 1, after ~5 seconds:
1) "message"
2) "__keyevent@0__:expired"
3) "cart:user:4711"

5. Further events: set, del, hset and more

Besides expired, Redis keyspace notifications support a wide range of further events that cover practically every relevant write operation. The g flag enables generic events like del, rename_from, rename_to and expire, the dollar sign flag enables string events like set, the h flag enables hash events like hset and hdel, the l flag enables list events like lpush and rpop, the z flag enables sorted set events like zadd. Each of these categories can be enabled independently to receive exactly the events an application actually needs to process.

An example of combining several event types: a cache invalidation system wants to react to both set and del events to update or remove dependent derived data in a second system. With the flag KEA$g, both keyspace and keyevent channels for string and generic events are enabled, so a single subscriber process can react to both kinds of changes without needing two separate configurations.


# Enable string ($) and generic (g) events, both keyspace (K) and keyevent (E)
redis-cli> CONFIG SET notify-keyspace-events KEA$g

# Subscribe with a pattern to catch both set and del events
redis-cli> PSUBSCRIBE "__keyevent@0__:set" "__keyevent@0__:del"
Reading messages... (press Ctrl-C to quit)

# In another terminal:
redis-cli> SET product:catalog:1001 "..."
redis-cli> DEL product:catalog:1001

# Subscriber receives, in order:
1) "pmessage"
2) "__keyevent@0__:set"
3) "__keyevent@0__:set"
4) "product:catalog:1001"
1) "pmessage"
2) "__keyevent@0__:del"
3) "__keyevent@0__:del"
4) "product:catalog:1001"

6. Reactive architecture: a practical example

An end-to-end example of a reactive architecture with Redis keyspace notifications is a session timeout system in an e-commerce application. Every active user session is stored as a Redis key with a TTL that gets extended on every user interaction. If the TTL expires without an extension, the expired event signals that the session has become inactive. A subscriber process reacts by persisting the user's shopping cart if that has not happened yet, sending analytics events about session duration and possibly releasing inventory that was reserved but never purchased.

This pattern works without additional cron jobs or schedulers that would have to periodically search for expired sessions. The entire reaction logic is event driven and runs exactly when the event actually occurs, not delayed until the next scan interval. For systems with many short lived state transitions, such as rate limiter resets, temporary locks or feature flag expiry, the same pattern can be used to model numerous further reactive workflows, without extending the architecture with a separate message queue.

7. Reliability: why Pub/Sub offers no guarantees

A central pitfall of Redis keyspace notifications is the underlying Pub/Sub semantics: Redis Pub/Sub is a fire and forget mechanism without persistence. If no subscriber is connected when an event occurs, the message is irrevocably lost, there is no queue from which it could be recovered later. A subscriber that briefly loses its connection, for example due to a network error or a deployment restart, misses all events that occur during that time, without any error notification.

This property makes Redis keyspace notifications unsuitable for use cases that require guaranteed delivery of every single event, such as billing or audit systems. For use cases such as cache invalidation or session cleanup, an occasionally lost event is usually uncritical, because a subsequent access reveals the inconsistency anyway, or a periodic fallback scan serves as a safety net. Anyone who needs genuine delivery guarantees should reach for a different Redis data structure.

8. Alternatives: Redis Streams for guaranteed delivery

Redis Streams, introduced in Redis 5.0, offer a persistent, log based alternative to Pub/Sub with significantly stronger delivery guarantees. While Pub/Sub messages disappear immediately after being sent, stream entries remain in memory until explicitly removed, and consumers can use consumer groups with XREADGROUP to reliably track which entries have already been processed. A consumer that was temporarily offline can, upon reconnecting, process all entries accumulated during the downtime, which is fundamentally impossible with Pub/Sub.

In practice this means: Redis keyspace notifications are excellent as a trigger mechanism that informs a system about a change, while the actual, reliable processing should run through a stream or an external message queue once delivery guarantees matter. A common pattern combines both: a lightweight subscriber receives the expired event and immediately writes it into a Redis stream, where it is further processed with full delivery guarantees.

9. Keyspace notifications compared to polling and streams

The choice between polling, keyspace notifications and streams depends on the requirement profile for latency, load and delivery guarantee. The following table contrasts the central properties.

Property Polling Keyspace notifications Redis Streams
Latency until reaction Depends on poll interval Near instant Near instant
Delivery guarantee Yes, since state is read directly None, fire and forget Yes, with consumer groups
Load on Redis High with short intervals Low, event driven Low to moderate
Implementation effort Low Low Medium
Recommendation Only at low criticality Trigger for uncritical reactions Critical, delivery guaranteed workflows

For most reactive use cases in the caching and session domain, Redis keyspace notifications are the right compromise between simplicity and reaction speed. However, as soon as every single event must be processed reliably, for example in billing or audit trails, the path leads through Redis Streams or a dedicated message queue.

10. Summary

Redis keyspace notifications turn every relevant write operation and every key expiry into a Pub/Sub event that applications can react to without polling. Activation happens via notify-keyspace-events with a combination of K and E flags for channel types plus further flags for concrete event categories such as expired, set or del. Subscribers typically subscribe to keyevent channels such as __keyevent@0__:expired to react to a specific event type in a targeted way.

The decisive caveat: Redis Pub/Sub offers no delivery guarantees, lost connections lead to lost events with no recovery possible. For uncritical, reactive workflows such as cache invalidation or session cleanup, that is usually acceptable, for use cases with hard delivery requirements, Redis Streams with consumer groups should be used instead. Applied correctly, keyspace notifications replace expensive polling with genuine event driven architecture, without introducing an additional message queue into the infrastructure.

Redis keyspace notifications, the essentials at a glance

Activation

notify-keyspace-events with K and E for channel types, plus flags such as x for expired or g for generic events.

Two channel types

Keyspace channel delivers the event name per key, keyevent channel delivers the key name per event type.

No delivery guarantee

Pub/Sub is fire and forget, offline subscribers miss events irrevocably, no way to catch up.

Alternative when needed

Use Redis Streams with consumer groups instead of plain Pub/Sub for guaranteed delivery.

11. FAQ: Redis Keyspace Notifications for Reactive Architectures

1Enabled by default?
No, must be explicitly enabled via notify-keyspace-events.
2What do K and E mean?
K keyspace channels, E keyevent channels, at least one required.
3How to subscribe to expired?
Enable Ex, then SUBSCRIBE __keyevent@0__:expired.
4Keyspace vs. keyevent channel?
Keyspace delivers event name per key, keyevent delivers key name per event.
5Reliably delivered?
No, fire and forget, offline subscribers permanently miss events.
6What event types exist?
del, set, hset, lpush, zadd and many more via their own flags.
7Alternative for guarantees?
Redis Streams with consumer groups for guaranteed delivery.
8Noticeable overhead?
Minimal with targeted activation, higher with all event classes and high write rate.
9Usable for cache invalidation?
Yes, common pattern via set and del events.
10Works in Redis Cluster?
Yes, but each node only publishes its own keys, subscriber must connect to all nodes.