Read-Through and Write-Through Caching with Redis
Cache-aside puts the caching logic in your application. Read-through and write-through move it into the cache layer itself, so the application talks to the cache as if it were the database and the cache handles loading from and writing to the backing store. The difference sounds subtle, but it changes who owns the logic, how consistent the cache stays, and where the complexity lives. Knowing all three patterns lets you pick the right consistency-versus-complexity tradeoff per use case.
This is part 10 of the Redis Masterclass, following cache-aside.
Read-through: the cache loads on a miss
In read-through, the application always reads from the cache, and the cache is responsible for fetching from the database on a miss. Where cache-aside has the application do the "load from DB and populate" step, read-through hides that behind the cache layer:
// application code is simple: just read from the cache
const user = await cache.get(`user:${id}`);
// the cache layer, on a miss, loads from the DB, stores it, and returns it
The behavior is nearly identical to cache-aside from the outside: lazy loading, TTLs, misses populate the cache. The difference is where the logic lives. Read-through requires a cache that can call your database (a provider, a library, or a wrapper you build), so the loading logic is centralized in one place instead of repeated at every call site.
The advantage is consistency of implementation: every read goes through the same loading path, so you can't forget to populate the cache in one code path. The cost is that you need that cache-with-loader layer. In practice, many teams get read-through's benefit by wrapping cache-aside in a single shared function, which is the same idea without special infrastructure.
Write-through: the cache writes to the database
Write-through pairs with read-through on the write side. The application writes to the cache, and the cache synchronously writes to the database before acknowledging:
// application writes to the cache; the cache writes through to the DB
await cache.set(`user:${id}`, updatedUser);
// internally: cache updates Redis AND writes to the database, then returns
Both the cache and the database are updated in one operation, so the cache is always consistent with the database (no stale entries from a forgotten invalidation). Every write keeps them in lockstep.
The tradeoff is write latency. Because the write goes to both the cache and the database synchronously, a write is as slow as the database write plus the cache write. You've added the cache to the write path, so writes don't get faster (reads do). And you're caching data on write whether or not it'll ever be read, which can fill the cache with cold data.
Read-through plus write-through: consistent but not faster to write
Used together, read-through and write-through give a cache that stays consistent with the database automatically: reads populate on miss, writes update both stores. The application treats the cache as its interface to data, and the cache keeps itself in sync. This is appealing when you want strong cache consistency without scattering invalidation logic through the app.
The honest limitations: writes aren't faster (they hit both stores), the cache holds data that may never be read (written on every write), and you need the cache layer to support the pattern. It shines for read-heavy data where consistency matters and you want the caching logic centralized, and it's overkill for simple caching where cache-aside's delete-on-write is enough.
Choosing between the patterns
Here's how the three compare so far:
- Cache-aside: application manages the cache; load on miss, invalidate on write. Simplest, most common, degrades gracefully, but the logic is spread across the app and can be applied inconsistently.
- Read-through: the cache loads on miss, centralizing read logic. Same behavior as cache-aside, cleaner if you have a cache layer that supports it.
- Write-through: the cache writes synchronously to the database, keeping cache and database consistent, at the cost of write latency and caching unread data.
A common, pragmatic setup is cache-aside reads with write-through-style consistency achieved by updating the database and invalidating the cache in one well-tested shared function, getting most of the benefit without a special cache provider.
Where consistency comes from
The real theme across these patterns is where cache consistency is enforced. Cache-aside relies on the application remembering to invalidate. Write-through enforces it structurally, because every write updates both stores. If forgotten invalidations are causing stale-cache bugs, moving to a write-through-style pattern (or centralizing the invalidation) fixes them by making consistency automatic rather than a thing developers must remember.
Read-through and write-through trade the application's control for the cache's automatic consistency. They're the right call when you want centralized, hard-to-forget cache logic and can tolerate write-through's latency. When you want simplicity and graceful degradation, cache-aside remains the workhorse. The next patterns push further: write-behind trades consistency for write speed, and refresh-ahead trades work for avoiding misses entirely.
Key takeaways
- Read-through moves the load-on-miss logic into the cache layer, centralizing it so no code path forgets to populate the cache.
- Write-through has the cache write synchronously to the database, keeping cache and database consistent automatically.
- Write-through doesn't speed up writes (they hit both stores) and caches data on write whether or not it's ever read.
- Read-through and write-through together give automatic cache consistency at the cost of write latency and a supporting cache layer.
- A practical alternative is cache-aside reads plus a shared update-DB-and-invalidate function, getting consistency without special infrastructure.
Frequently asked questions
What's the difference between cache-aside and read-through?
In cache-aside the application loads from the database on a miss and populates the cache. In read-through the cache layer does that loading itself, so the application just reads from the cache. The behavior is similar, but read-through centralizes the logic.
What is write-through caching?
A pattern where the application writes to the cache and the cache synchronously writes to the database before returning. Both stores are updated together, keeping the cache consistent with the database at the cost of higher write latency.
Does write-through make writes faster?
No. Writes go to both the cache and the database synchronously, so they're at least as slow as the database write. Write-through improves read consistency, not write speed; reads benefit because the cache is always populated and current.
When should I use read-through and write-through over cache-aside?
When you want cache consistency enforced automatically and the caching logic centralized rather than spread across the app, and you can tolerate the extra write latency. For simple caching with graceful degradation, cache-aside is usually enough.
How do I keep the cache consistent without write-through?
Use cache-aside but centralize writes in a single shared function that updates the database and invalidates the cache together. This makes invalidation hard to forget, approximating write-through's consistency without a special cache layer.

About the author
I'm Aman Kumar Singh, a software engineer in Noida, India building scalable full-stack products with React, Next.js, Node.js, NestJS, PostgreSQL, Redis, and AWS. I write about backend engineering, distributed systems, and system design.