Cache strategies, data structures, consistency, expiration, clustering, persistence and production diagnostics.
Topics
41
Sections
6
Learning module
Redis learning module
Redis is an in-memory data structure store used by millions of developers as a cache, vector database, document database, streaming engine and message broker.
One command thread makes every command atomic, and a slow one blocks everybody.
Use SCAN, never KEYS, on production data.
Cache-aside: write the database, then delete the key; add TTL jitter.
Replication is asynchronous, so a failover can lose acknowledged writes.
A primary database that cannot absorb every read: Without a cache, every page view hits the primary database: hot rows are re-read thousands of times per second, latency climbs under load, and features such as rate limits, sessions, counters and leaderboards turn into contended row updates. Redis serves that hot data from memory in sub-millisecond time with atomic operations on purpose-built types, so the database handles writes and complex queries while Redis absorbs the repetitive, latency-sensitive traffic.
Client hooks & events
Client error events
Attach an error listener at creation: an unhandled client error can take the process down.
Attach the client's error listener before initiating a connection.
Record the operation context without logging credentials.
Treat error notifications separately from per-command promise failures.
Connection lifecycle events
connect, ready, reconnecting and end are the states a pool's health check should read.
Distinguish connecting, ready, reconnecting and closed states.
Gate operations on the readiness guarantees of the chosen client.
Release listeners and connections during application shutdown.
Reconnect strategy
Supply a backoff function so a flapping server is not hammered by every instance at once.
Use bounded exponential reconnect delay with jitter.
Avoid a tight retry loop during a Redis outage.
Decide whether queued commands remain valid after reconnection.
reconnectOnError
Decide per error whether the client should reconnect, for cases such as a failed-over replica.
Use reconnectOnError only with a client that supports it.
Select the server errors that justify reconnecting deliberately.
Consider duplicate writes before automatically resending a failed command.
Keyspace notifications
Subscribe to expiry and eviction events instead of polling for keys that vanished.
Enable only the notification classes the application needs.
Subscribe to the correct database and event channels.
Notifications are ephemeral and cannot replace a durable event log.
Client-side cache invalidation
CLIENT TRACKING pushes invalidation messages so a local cache can drop a stale entry.
Enable tracking with a client and server that support it.
Remove local entries when invalidation messages arrive.
Define recovery behavior when the invalidation connection is lost.
Pub/Sub message handlers
A subscriber connection cannot run ordinary commands, which shapes how handlers are wired.
Use a dedicated subscription connection where the client requires one.
Keep message handlers fast and catch processing failures.
Resubscribe after reconnecting without assuming missed messages are replayed.
Server-side scripts as hooks
A Lua script or function runs atomically on the server, where a read-modify-write would race.
Execute bounded Lua scripts or registered functions near the data.
Pass accessed keys explicitly for cluster-aware execution.
Avoid slow scripts that block other server work.
Redis foundations
Keys and namespacing
Design stable keys that include entity and tenant boundaries; distinguish missing keys from empty values.
Include application, tenant and data purpose in key names.
Choose a predictable version suffix when payload shape changes.
Use SCAN rather than blocking key enumeration in production.
Strings and counters
Store byte strings and use atomic increments for counters instead of client-side read-modify-write.
Use GET and SET for byte strings or serialized values.
Use atomic INCR operations for counters.
Set expiry explicitly when a counter belongs to a time window.
Hashes
Group named fields for an entity and compare field-level updates with replacing one serialized value.
Store related fields in one hash when partial updates are useful.
Read or update only the fields the operation needs.
Bound hash size and avoid mixing unrelated ownership scopes.
Lists
Use ordered sequences for suitable queue-like patterns while checking reliability requirements.
Push and pop values from the intended end of the list.
Use blocking operations carefully with dedicated worker connections.
Prefer streams when acknowledgements and durable consumer tracking are needed.
Sets
Represent unique membership and use set operations when order is irrelevant.
Use sets for unique membership and set operations.
Check membership without downloading the entire set.
Watch memory growth when storing unbounded user-generated values.
Sorted sets
Associate members with scores for ranking, scheduling and bounded range queries.
Associate each unique member with a numeric ordering score.
Query bounded score or rank ranges for leaderboards.
Define tie-breaking and pagination behavior explicitly.
Streams
Store append-oriented event records and track consumer progress with the supported stream mechanisms.
Append events with ordered stream IDs.
Use consumer groups and acknowledge completed processing.
Inspect pending entries and reclaim abandoned work.
JSON and search capabilities
Check the deployed Redis capabilities before relying on document storage or secondary search features.
Check which JSON and search features the deployment supports.
Define indexes around actual query and filter patterns.
Measure write amplification and index memory separately from cached values.
Caching patterns
Cache-aside
Load the source of truth on a miss, populate Redis and define how writes invalidate cached values.
Read the cache before loading from the source database.
Populate misses with a bounded TTL.
Invalidate or refresh entries after authoritative writes.
Read-through caching
Place retrieval logic behind a cache abstraction so callers use one read contract.
Use a cache layer that loads missing values on behalf of callers.
Keep the loader's errors distinct from a valid missing record.
Coalesce concurrent loads for the same key.
Write-through caching
Coordinate source writes and cache updates and document what happens when one succeeds and the other fails.
Update the cache as part of the application's write path.
Define recovery when the database write and cache update disagree.
Keep the database as the explicit authority unless designed otherwise.
Write-behind tradeoffs
Buffer writes only when delayed persistence and potential loss match the business requirements.