Caching strategies decide which responses are computed once and reused, and which must always hit the database. A product page, a permission check or a full HTML document that is rebuilt on every request wastes the server and makes the site slow exactly when traffic arrives. The business result is timeouts at checkout, a database at full CPU and a hosting bill that grows with visitors instead of with real work.
Contents
At CodeWiz we design caching across the whole path: Redis or Memcached beside the application, caches inside Laravel, Node.js and WordPress, an HTTP cache such as Varnish or Nginx, and a CDN in front. We care as much about invalidation as about the hit. A fast page that shows yesterday’s price is not a win.
This service is for stores and content sites that slow down under load, for APIs that repeat the same heavy queries, and for teams that already added a cache and now cannot explain why it serves stale or private data. If the site is fast and the database is idle, we will say that another layer is not worth the complexity.

Redis Caching Strategies for Hot Data, Sessions and Locks
Redis is an in-memory store with rich data types, sub-millisecond reads and explicit control over eviction. It is the default shared cache when more than one application server must see the same values: rendered fragments, query results, rate-limit counters, distributed locks and sessions. We keep those jobs apart. A cache may forget a key. A session or a queue must not.
- Cache-aside. The application reads Redis first and fills the key on a miss, with a TTL that matches how stale the data may be. Writes delete or update the key in the same request that changes the database.
- Separate instances or databases. The cache uses
allkeys-lruorvolatile-lruand a memory cap. Sessions, locks and queues usenoevictionso Redis refuses a write instead of deleting a login. - Stampede control. When a popular key expires, one worker recomputes it and the others wait or serve a slightly stale value. Otherwise a hundred identical queries hit PostgreSQL or MySQL at once.
- No persistence for a pure cache. Snapshots and AOF slow a cache that is allowed to start empty. We turn them on only for data that must survive a restart.
Eviction policy and memory limits are covered in the Redis eviction reference and in the server memory optimization notes. We document the keys, TTLs and the instance split in the repository so the next developer does not guess.
Memcached Setup for a Simple Shared Cache
Memcached is a smaller idea done well: a multithreaded key-value cache, no persistence, no rich types, consistent hashing across nodes. It fits when the only operation you need is “store this blob, get it back, let it expire”. Magento and some older PHP stacks already speak Memcached, and replacing it with Redis on day one is not always the project.
When we choose it, and when we do not
- Choose Memcached for shared fragments and query results on a fleet of application servers that only need get and set.
- Stay with Redis when you also need locks, lists, pub/sub, rate limiting or data that must not be evicted.
- Size the slab and the item limit so a few large pages do not push out thousands of small keys.
- Put Memcached on a private network, with authentication where the version supports it, never on a public port.
A Memcached setup from us includes the client configuration in the app, a memory budget, health checks and the same invalidation rules we would write for Redis. The protocol is simpler. The mistakes, especially caching a personalised page under a shared key, are the same.
Application Caching Strategies in Laravel, Node.js and WordPress
Application caching is the layer the code controls. It stores objects, query results and HTML fragments under keys the developers name. It is the right place for “this category tree is expensive and changes a few times a day”, and the wrong place for “this whole HTML page, including the logged-in user’s name”.

In Laravel we use the cache store (Redis in production, array or file only in local tests), Cache::remember for the read path and explicit forget or tags when a model is saved. In WordPress we install a persistent object-cache drop-in so options, posts and query results stop hitting MySQL on every request, and we still keep page caching at the HTTP layer for anonymous traffic. In Node.js the same cache-aside pattern sits in a small module, shared by the API and the workers, with one function that knows the key format.
$product = Cache::remember("product:{$id}", 300, function () use ($id) {
return Product::with('category')->findOrFail($id);
});
// called from the model observer when the product is saved
Cache::forget("product:{$id}");- Keys include every dimension that changes the value: id, locale, currency, tenant. A missing dimension is how one visitor sees another’s price.
- In-process caches (APCu, a Node Map) are extra fast and invisible to other servers. We use them for tiny, rarely changing lookups, not as the only cache on a multi-server deploy.
- Framework caches do not replace HTTP caching. An object cache still runs PHP or Node on every hit. A full-page cache can skip the application entirely.
CDN Optimization and Edge Cache Rules
A CDN stores responses close to the visitor. For a shop or a publisher with readers outside the origin’s city, that round trip is often the largest part of waiting. CDN optimization is not “turn caching on”. It is a set of rules for what may be stored, for how long, and how a publish or a stock change removes it.
- Static assets use long lifetimes and versioned filenames, so a deploy does not wait on a purge.
- HTML is cached only when it is anonymous. A cookie or an
Authorizationheader bypasses the edge unless we have deliberately built a cache key that excludes the session. - Tracking query parameters are stripped from the cache key, otherwise every campaign link is a miss.
- Purge by URL or by tag when content changes, with a fallback TTL so a missed purge still expires.
- Cache rules live in the repository or in an exported config, not only in a dashboard somebody edited once.
We usually do this on Cloudflare. The Cloudflare cache documentation is the reference for cache keys, rules and purge. How those rules fit a fast origin is the subject of our notes on Cloudflare configuration for performance and on reaching strong Core Web Vitals scores. Google’s own guidance is an LCP under 2.5 seconds; edge caching of anonymous HTML and assets is one of the reliable ways to get there.

Invalidation, HTTP Caching and Stampedes
The hard part of every cache is knowing when a stored value is no longer true. TTL alone means a price can be wrong until the timer fires. Delete-on-write alone fails when a second system updates the row, or when the CDN still holds the HTML. We combine both, and we name the owner of each key.
- TTL as a backstop. Even keys we delete on write get a lifetime, so a missed event cannot pin a stale value forever.
- Tags and versioned prefixes. “All product pages for tenant 18” can be dropped without listing every URL. A prefix bump abandons a whole generation of keys.
- HTTP validators.
Cache-Control,ETagandstale-while-revalidatelet the browser and the CDN refresh without a thundering herd. - Varnish or Nginx in front of the origin for sites where full-page hits should never execute PHP. We have written separately about Varnish as the HTTP cache in that role. PURGE and bans follow the same events that delete Redis keys.
Which Layer Should Cache What
Most slow applications need two layers, not five. These caching strategies stay small on purpose. We pick from this map and skip the rest until measurement says otherwise.
| Layer | Typical tool | Stores | Expires by | Best for |
|---|---|---|---|---|
| Browser | Cache-Control | Assets, some HTML | max-age, versioned filenames | Static files, repeat visits |
| CDN | Cloudflare | Assets, anonymous HTML, some API | TTL, purge by URL or tag | Visitors far from the origin |
| HTTP cache | Varnish, Nginx | Full responses | TTL, PURGE, bans | High-traffic pages that can skip the app |
| Application | Laravel, WordPress, Node.js | Objects, fragments, query results | TTL, keys, tags | Expensive work reused across requests |
| Shared cache | Redis, Memcached | Objects, sessions, locks, counters | TTL plus explicit delete | Many app servers, one shared truth |
A useful target is a high hit ratio on the keys that are expensive, a drop in queries per page and a stable time to first byte. We read those from the cache stats, the database’s slow log and the browser, not from a feeling that “it seems faster”.
Common Caching Mistakes We Fix
- One cache key for a page that contains the logged-in user’s name, cart or price list.
- Redis with no
maxmemorypolicy, so it either dies when RAM fills or evicts sessions along with the cache. - No TTL and no delete on write, so a price or a stock count lives until someone restarts the process.
- Caching error responses and 404s, then serving them long after the origin has recovered.
- A local in-process cache on several servers, each holding a different version of the same object.
- A CDN cache key that includes every query parameter, so analytics tags make every URL a miss.
What Drives the Cost of a Caching Project
Redis and Memcached are open source. The cost is the design and the care around invalidation, not a licence. We estimate after a look at traffic, the heaviest queries and how content is published:
- How many layers are actually missing. Object cache alone is smaller than object cache plus Varnish plus CDN rules.
- Whether pages are anonymous and cacheable, or personalised on every view.
- How many code paths write the data. One admin screen is simple. Five integrations writing stock are not.
- Memory and number of nodes once the working set no longer fits one small instance.
- A one-off setup versus us keeping keys, TTLs and purge rules in line with later features.
How We Work
- Audit: we measure slow requests, query counts, response headers and whatever cache is already in place.
- Plan: we choose the layers, the keys, the TTLs and the events that invalidate them, and we skip layers you do not need.
- Build: we add Redis or Memcached, the application calls, HTTP or CDN rules, and dashboards for hit ratio and memory.
- Test: we check a miss, a hit, a purge after an edit, and a logged-in page that must not be shared.
- Launch: we enable caching in steps, watch origin traffic and error rates, and keep a quick way to bypass a bad rule.
- Support: we document the key scheme and can review new features so they invalidate what they change.
Why CodeWiz
- We build the applications: Laravel, WordPress, WooCommerce and Node.js caches are designed with the code that writes the data.
- Open-source first: Redis, Memcached, Varnish and Nginx, with Cloudflare at the edge when a global cache is the right tool.
- Fewer layers, not more: if a plugin and a tuned database are enough, we will not sell you a three-tier cache.
- Fair pricing: premium development without premium prices, from Banja Luka, working remotely with clients locally and internationally.
- Performance in one place: database queries, caching and the CDN are one plan. More about CodeWiz.
Frequently Asked Questions
How much does a caching project cost?
Adding Redis and a handful of cache-aside calls around the slowest queries is a small engagement. Full-page caching, CDN rules and invalidation across a store with personalised prices is larger. You get an estimate after we see the traffic and the code paths that write the data.
Should we use Redis or Memcached?
Redis, unless you already run Memcached and only need simple get/set. Redis covers cache, locks, counters and queues, with an eviction policy we can set per instance. Memcached stays when the stack already depends on it and the extra types are unused.
Will caching show stale prices or private pages?
Only if invalidation and the cache key are wrong. We delete or purge on write, keep a TTL as a backstop, and refuse to store a response that depends on the logged-in user under a shared key. Those cases are part of the test plan before launch.
Do I need Redis, Varnish and a CDN together?
Not by default. A CDN plus sensible browser headers fixes a lot of asset and anonymous-page latency. Redis fixes repeated work inside the application. Varnish earns its place when the origin still renders the same public HTML thousands of times. We add a layer when the measurements show a gap, not because the diagram looks complete.
Can you add caching without rewriting the application?
Often, yes. An HTTP cache and a CDN sit in front of an unchanged app, and a WordPress object-cache drop-in does not require new business logic. The largest gains inside the code are still a few deliberate cache-aside calls, which we can add without a redesign.
How do you know the cache is working?
Hit ratio on the expensive keys, fewer queries per page, lower origin traffic at the CDN and a time to first byte that stays steady during a spike. We also test the negative: after an edit, the old value is gone, and a logged-in response is not reused for someone else.
Make the Slow Pages Fast on Purpose
Tell us which pages or endpoints hurt and what you already cache. We will propose caching strategies that match the traffic, with a clear rule for when each value is thrown away. Contact us to talk it through, or see our caching strategy services.