skip to content

Redis's CLIENT TRACKING command accepts OPTIN and OPTOUT modes, paired with a CLIENT CACHING yes|no command. What do they control and why would you want that control?

level: middleimportance: nice to knowfreq 24%

answer

  1. OPTIN = whitelist, needs CLIENT CACHING YES
  2. OPTOUT = blacklist, CLIENT CACHING NO
  3. flag applies to the NEXT command only
  4. mutually exclusive; neither works with BCAST
  5. goal: smaller tracking table, less push traffic

basics

~20 s

They select which read keys the server bothers to track. OPTIN tracks nothing unless the client sends CLIENT CACHING YES immediately before a read; OPTOUT tracks everything except after CLIENT CACHING NO. Both shrink the server's tracking table and the invalidation traffic to only the keys the client actually caches locally.

solid answer

~60 s

By default, tracking records **every** key the connection reads, whether or not the client intends to cache it. That wastes server memory in the invalidation table and generates invalidation pushes the client will just discard. - `CLIENT TRACKING on OPTIN` — nothing is tracked unless the client sends `CLIENT CACHING YES` right before the read command it wants tracked. Whitelist semantics: good when only a few keys are locally cacheable. - `CLIENT TRACKING on OPTOUT` — everything is tracked except reads preceded by `CLIENT CACHING NO`. Blacklist semantics: good when most reads are cacheable and a few (huge values, one-shot lookups) are not. The `CLIENT CACHING` flag applies to the **next command only** (a MULTI/EXEC block counts as one unit), so a client library typically emits it in the same pipeline batch as the read. You can enable one or the other, never both, and neither is compatible with `BCAST`, where the prefixes already define the scope. The practical payoff is a smaller `tracking-table-max-keys` footprint and fewer pointless invalidation messages.

code

text · 9 lines
text
CLIENT TRACKING on OPTIN
OK
GET session:v1:abc          # not tracked, no invalidations for it

CLIENT CACHING YES
OK
GET config:v1:flags         # tracked -> invalidation push on change

GET config:v1:flags         # not tracked: the flag covered one command only

go deeper

for a junior

Know that OPTIN means keys are tracked only when explicitly requested and OPTOUT means everything is tracked except when explicitly declined.

for a middle

Explain the per-next-command scope of CLIENT CACHING, the mutual exclusivity, and why filtering saves tracking-table memory and push traffic.

for a senior

Choose the mode from the read/cacheable ratio, note that BCAST is the alternative when prefixes describe the set, and use CLIENT TRACKINGINFO to verify library behavior.

for a principal

Own the policy across services: which data classes are locally cacheable at all, how tracking-table budget is shared on a multi-tenant instance, and where BCAST replaces per-key tracking entirely.

## The default is indiscriminate With plain `CLIENT TRACKING on`, Redis records **every key the connection reads** into its global invalidation table, mapping key to the set of interested client IDs. That is a fine default and matches the common case — an application that locally caches whatever it fetches. But real applications read plenty of things they will never cache locally: a 4 MB blob fetched once for an export job, a per-request one-shot lookup that will never be read again, a scan of many keys during a batch. Tracking those costs on both sides: - **Server memory.** Each tracked key consumes an entry in the invalidation table, capped by `tracking-table-max-keys` (default 1,000,000). Filling the table with keys nobody caches pushes out entries for keys clients *do* cache, and evictions from that table trigger spurious invalidations to real consumers. - **Network and CPU.** Every modification of a tracked key produces a push message to each interested client. If the client is going to drop the message on the floor because it never cached the key, that traffic was pure waste — and on a write-heavy key it can be a lot of traffic. OPTIN and OPTOUT exist to align what the server tracks with what the client actually caches. ## OPTIN — whitelist `CLIENT TRACKING on OPTIN` turns tracking off by default for this connection. Nothing is remembered unless the client explicitly says so, per read, by sending `CLIENT CACHING YES` **immediately before** the read command: ``` CLIENT TRACKING on OPTIN GET session:v1:abc # NOT tracked CLIENT CACHING YES GET config:v1:flags # tracked GET config:v1:flags # NOT tracked again (the flag applied to one command) ``` The key subtlety: the caching flag is **valid for the next command only**. If that next command is `MULTI`, it applies to the whole transaction up to `EXEC`. It does not persist, so a client library that wants a key tracked must emit the pair every time — usually written into the same pipeline batch so it is still one round trip. OPTIN suits applications where a small, known set of keys is locally cacheable — configuration, flags, reference data — and the bulk of traffic is one-shot. ## OPTOUT — blacklist `CLIENT TRACKING on OPTOUT` inverts it: everything read on this connection is tracked, except commands preceded by `CLIENT CACHING NO`. ``` CLIENT TRACKING on OPTOUT GET user:v1:42 # tracked CLIENT CACHING NO GET export:v1:bigblob # NOT tracked ``` This suits applications where nearly everything is locally cached and the exceptions are identifiable — very large values you would never hold in process memory, or keys known to churn constantly. ## Mutual exclusivity and BCAST You cannot enable both: `CLIENT TRACKING on OPTIN OPTOUT` is rejected, and switching from one to the other requires turning tracking off first. Attempting `CLIENT CACHING` when tracking is off, or in the mode where it makes no sense (a `YES` under OPTOUT, a `NO` under OPTIN), is an error rather than a silent no-op — which is helpful, because it surfaces client-library bugs immediately. Neither mode combines with `BCAST`. In broadcast mode the server does not remember per-key interest at all; it broadcasts invalidations for registered key prefixes, so the prefix list *is* the selection mechanism and a per-command opt-in would have nothing to attach to. Redis rejects the combination. ## Practical notes - **Who emits these?** Almost always the client library, not application code. A well-built client exposes "cacheable" as a per-call hint and translates it into the `CLIENT CACHING` prefix, batching it with the read so no extra round trip is paid. - **Diagnosing.** `CLIENT TRACKINGINFO` reports the connection's flags, and you will see `optin`/`optout` plus a transient `caching-yes`/`caching-no` when a flag is pending for the next command. It is the fastest way to confirm the library is doing what you think. - **Choosing.** Estimate the ratio: if under roughly half your reads are locally cached, OPTIN; if the large majority are, OPTOUT; if the cacheable set is neatly described by key prefixes and you have very many connections, consider BCAST instead, which sidesteps per-key bookkeeping entirely. - **It changes tracking, not correctness.** An untracked key is simply one you will not be told about — so if the client caches it anyway, it will be stale forever. Whatever the mode, the rule stays: only locally cache what is tracked, and always keep a local TTL as a backstop.

  • How long does a CLIENT CACHING YES flag remain in effect?
    For the next command only. If that command is MULTI, it covers the whole transaction through EXEC. It does not persist across subsequent reads, so a client that wants several keys tracked must emit the flag before each read — typically batched into the same pipeline so no extra round trip is paid.
  • Why can't OPTIN or OPTOUT be combined with BCAST?
    In broadcast mode the server keeps no per-key record of which client read what; it simply broadcasts invalidations for the key prefixes each client registered. The prefix list is therefore already the selection mechanism, and a per-command opt-in has nothing to attach to. Redis rejects the combination outright rather than silently ignoring it.
  • What do you actually save by using these modes?
    Server memory in the invalidation table, which is capped by tracking-table-max-keys — filling it with keys nobody caches evicts entries for keys clients do cache and causes spurious invalidations. You also save network and CPU on push messages the client would discard, which matters most for keys that are read once but written often.

OPTIN is telling the publisher 'send me errata only for the chapters I ask about'; OPTOUT is 'send me everything except the appendix I never read'.

saying these in an interview costs you the question

  • Believing CLIENT CACHING YES stays in effect for the rest of the connection.
  • Thinking OPTIN and OPTOUT can be enabled at the same time, or alongside BCAST.
  • Assuming the modes change invalidation correctness rather than which keys are tracked.
  • Caching a key locally that was never opted into tracking, so no invalidation will ever arrive for it.
  • Putting CLIENT CACHING calls in application code instead of the client library, adding a round trip per read.

context