Chat

Redis Caching Patterns for Next.js and Node

Behind-the-scenes caching that customers only feel as speed: Redis TTLs, stampede protection, tag invalidation, request coalescing, and what not to cache in Next.js apps.

Customers do not know you run Redis. They know whether product pages feel instant. Caching is invisible development work — and one of the easiest ways to ship subtle bugs if you cache the wrong thing.

This is the Redis playbook we use behind Next.js apps, Node APIs, and high-read dashboards.

What belongs in Redis vs what does not

Good fit: hot read models, computed aggregates, rate-limit counters, session blobs you intentionally designed, feature-flag snapshots, idempotency records with TTL.

Bad fit: authorization decisions without server re-check, unbounded lists, PII you are not allowed to retain, HTML that personalizes per user without varying the key.

Key design

Include tenant and entity in keys: `t:{tenant}:product:{id}:v{version}`. Never invent keys from only the URL if auth changes the payload.

Version or hash schema into the key so deploys do not serve incompatible JSON shapes.

TTL strategies

- Short TTL (5–60s) for near-real-time dashboards

- Medium TTL (5–30m) for product/category reads with explicit invalidation on writes

- Soft TTL + hard TTL: serve stale while one worker refreshes (stale-while-revalidate)

Hard infinite TTLs without invalidation are how you explain wrong prices at 2 a.m.

Cache stampede protection

When a hot key expires, 200 workers may rebuild it. Use a lock (`SET key nx ex`) so one worker refreshes while others wait or serve stale. Request coalescing inside a single Node process helps but does not replace distributed locks.

Tag-based invalidation

Associate keys with tags such as `product:123` and `category:shoes`. On write, delete by tag set. This is more reliable than hoping every writer remembers every key string.

If you cannot do tags, invalidate conservatively on write paths and keep TTLs honest.

Next.js-specific notes

Next.js has its own data cache and `revalidate` model. Redis sits beside it for cross-instance shared state and API backends. Do not double-cache personalized RSC payloads in Redis without a user-aware key.

For ISR/SSG pages, prefer platform revalidation for HTML and Redis for origin API aggregation.

Observability

Track hit ratio, latency, eviction rate, and lock wait time. A 99% hit ratio with wrong data is not success. Pair cache metrics with business correctness checks on prices and stock.

Failure mode: Redis is down

Decide explicitly: fail open to DB (with shed load) or fail closed for non-critical features. Time out Redis calls aggressively. A hung cache client should not take down checkout.

Final takeaway

Redis caching is invisible when it works. Treat it as part of your domain model — keys, TTLs, invalidation, and failure modes — not as a mysterious speed switch.

Frequently asked questions

Should every Next.js app use Redis?

No. Use it when multiple instances need shared hot data, rate limits, or expensive aggregates. Many sites are fine with Next revalidation and a fast DB.

How do I prevent cache stampedes?

Use a distributed lock around rebuilds and consider serving stale data while refresh happens.

How should we invalidate product caches?

Prefer tag-based invalidation on write, plus a safety TTL. Do not rely on TTL alone for prices or stock.

Can we cache authenticated API responses?

Only with keys that include user or role context, short TTLs, and a clear rule that authorization still runs on the server.

Related links

Back to Blog