Valkey keyspace notifications are a way to broadcast events happening in your Valkey instance, like keys being added, removed, or expiring, to other clients.

Let’s see it in action. Imagine you have a Valkey instance running. You can subscribe to a specific channel that broadcasts these events.

valkey-cli
SUBSCRIBE __keyspace@0__:set

Now, in another terminal, interact with your Valkey instance:

valkey-cli
SET mykey "myvalue"

Back in the first terminal, you’ll see:

Reading messages... (press CTRL+C to quit)
1) "subscribe"
2) "__keyspace@0__:set"
3) (integer) 1
1) "message"
2) "__keyspace@0__:set"
3) "set"

This shows that a SET command was executed on mykey. The __keyspace@0__ part indicates the database (database 0 in this case), and set is the event type. You can subscribe to more general patterns or specific key events.

The core problem Valkey keyspace notifications solve is enabling reactive systems. Instead of constantly polling Valkey to see if something has changed, your application can be notified exactly when an event occurs. This is far more efficient and allows for real-time updates. Internally, Valkey has a pub/sub mechanism that, when enabled, publishes messages about key-level operations to designated channels.

The exact levers you control are the notify-keyspace-events configuration directive. This is a bitmask, meaning you combine different event types using the | (OR) operator.

Here are the common event types you can enable:

  • K: Keyspace notifications. This is the base event type.
  • E: Key-event notifications. This is another base event type.
  • g: Generic commands like DEL, EXPIRE, RENAME.
  • g: String commands like SET, GETSET, INCR.
  • h: Hash commands like HSET, HDEL.
  • z: Sorted set commands like ZADD, ZREM.
  • l: List commands like LPUSH, LRPOP.
  • s: Set commands like SADD, SREM.
  • u: Streams commands like XADD, XDEL.
  • A: All of the above.

To enable notifications for key expiration and generic commands, you would set it to KEg. If you want to be notified of all key-level events, you’d use AKE.

A common setup is to enable notifications for all key-level events and all generic commands. In your valkey.conf, you’d find or add:

notify-keyspace-events AKE

After modifying valkey.conf, you need to reload Valkey’s configuration. The easiest way to do this without restarting Valkey is to send the CONFIG REWRITE command:

valkey-cli CONFIG REWRITE

This command rewrites the configuration file with the current running configuration, including any dynamic changes you’ve made. If you’re not running Valkey in a way that supports CONFIG REWRITE (e.g., a read-only cluster), you’ll need to restart Valkey after editing valkey.conf.

The channels are structured as __keyspace@{db_number}__:{event_type} for keyspace notifications and __keyevent@{db_number}__:{command_name} for key event notifications. For example, subscribing to __keyspace@0__:expired will give you a notification whenever a key expires in database 0. Subscribing to __keyevent@0__:set will notify you for every SET command executed on database 0.

When you enable notify-keyspace-events, Valkey doesn’t just magically send messages; it internally hooks into its command execution pipeline. Each command that modifies a key or its metadata triggers a check against the notify-keyspace-events mask. If the event type matches an enabled mask, a message is constructed and published to the appropriate pub/sub channel. The efficiency comes from this being a push mechanism, unlike polling which requires continuous client requests.

A detail that often trips people up is the distinction between __keyspace@... and __keyevent@... channels. __keyspace@... channels broadcast the type of event that happened to a key (e.g., "set", "expired", "del"), and they are keyed by the database number and the event type. __keyevent@... channels broadcast the name of the command that was executed (e.g., "SET", "DEL", "EXPIRE"), and they are keyed by the database number and the command name. Many applications find it more useful to subscribe to __keyevent@... channels because they directly map to the commands they might want to react to.

After setting up notifications, the next natural step is to understand how to process these events efficiently in your application, perhaps using a dedicated consumer or a message queue.

Want structured learning?

Take the full Valkey course →