The performance of your app can be made or broken by caching, let’s face it. Caching is one of the most effective performance enhancers you can utilize whether developing a microservices backend, e-commerce website, or real-time dashboard. However, immense power also means amazing architectural choices! Every caching technique has advantages, disadvantages, and optimal use cases.
In this blog, we’ll demystify:
- Cache-Aside
- Write-Through
- Read-Through
- Write-Back
- Write-Around
And how to implement them (especially in .NET).
What is Caching?
Caching is storing frequently-accessed data in a faster and closer storage layer (like memory) so that future reads are quicker and less expensive.
Think of it like keeping your most-used apps on your phone’s home screen — instead of digging through folders every time.
Cache-Aside (Lazy Loading)
How does it work?
- The application checks the cache first.
- If the data isn’t there (cache miss), it’s loaded from the database, returned to the caller, and added to the cache.
Real-world analogy
You don’t remember a friend’s number. You look it up once, save it in contacts (cache), and reuse it next time.
Pros
- Simple and flexible
- Cache only stores what’s needed
- Easy to implement
Cons
- Cache miss penalty on the first request
- Stale data if the DB is updated elsewhere
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-async">async</span> <span class="token return-type class-name">Task<span class="token punctuation"><</span>Product<span class="token punctuation">></span></span> <span class="token function">GetProduct</span><span class="token punctuation">(</span><span class="token class-name"><span class="token keyword keyword-int">int</span></span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> cacheKey <span class="token operator">=</span> <span class="token interpolation-string"><span class="token string">$"product:</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">id</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> cached <span class="token operator">=</span> <span class="token keyword keyword-await">await</span> _cache<span class="token punctuation">.</span><span class="token function">GetStringAsync</span><span class="token punctuation">(</span>cacheKey<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword keyword-if">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword keyword-string">string</span><span class="token punctuation">.</span><span class="token function">IsNullOrEmpty</span><span class="token punctuation">(</span>cached<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword keyword-return">return</span> JsonSerializer<span class="token punctuation">.</span><span class="token generic-method"><span class="token function">Deserialize</span><span class="token generic class-name"><span class="token punctuation"><</span>Product<span class="token punctuation">></span></span></span><span class="token punctuation">(</span>cached<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name"><span class="token keyword keyword-var">var</span></span> product <span class="token operator">=</span> <span class="token keyword keyword-await">await</span> _db<span class="token punctuation">.</span>Products<span class="token punctuation">.</span><span class="token function">FindAsync</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword keyword-if">if</span> <span class="token punctuation">(</span>product <span class="token operator">!=</span> <span class="token keyword keyword-null">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword keyword-await">await</span> _cache<span class="token punctuation">.</span><span class="token function">SetStringAsync</span><span class="token punctuation">(</span>cacheKey<span class="token punctuation">,</span> JsonSerializer<span class="token punctuation">.</span><span class="token function">Serialize</span><span class="token punctuation">(</span>product<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword keyword-return">return</span> product<span class="token punctuation">;</span> <span class="token punctuation">}</span> |
How does it work?
- Write to the cache and the database simultaneously.
- The cache is always updated whenever the DB is updated.
Real-world analogy
Every time you update your address, you update both your driving license (database) and your phone’s contacts (cache).
Pros
- Cache always has fresh data
- Simple read logic (just use the cache)
Cons
- Slightly slower writes (due to double write)
- Not ideal for write-heavy systems
1 2 3 4 5 | <span class="token keyword keyword-public">public</span> <span class="token keyword keyword-async">async</span> <span class="token return-type class-name">Task</span> <span class="token function">SaveProduct</span><span class="token punctuation">(</span><span class="token class-name">Product</span> product<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword keyword-await">await</span> _db<span class="token punctuation">.</span>Products<span class="token punctuation">.</span><span class="token function">UpdateAsync</span><span class="token punctuation">(</span>product<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// DB write</span> <span class="token keyword keyword-await">await</span> _cache<span class="token punctuation">.</span><span class="token function">SetStringAsync</span><span class="token punctuation">(</span><span class="token interpolation-string"><span class="token string">$"product:</span><span class="token interpolation"><span class="token punctuation">{</span><span class="token expression language-csharp">product<span class="token punctuation">.</span>Id</span><span class="token punctuation">}</span></span><span class="token string">"</span></span><span class="token punctuation">,</span> JsonSerializer<span class="token punctuation">.</span><span class="token function">Serialize</span><span class="token punctuation">(</span>product<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Cache write</span> <span class="token punctuation">}</span> |
How does it work?
- The application never directly accesses the database.
- The cache is configured to load the data from the DB on cache misses automatically.
Real-world analogy
You ask your assistant for a file. If it’s not already in their drawer (cache), they fetch it from storage and give it to you (and remember it for next time).
Pros
- Centralized control
- Great for reducing boilerplate in apps
Cons
- Cache engine must support DB integration
- Less flexible at the application level
Implementation tip
You’ll typically need to wrap your cache layer or use a library like Redis Gears or integrate it at the repository level.
Write-Back (Write-Behind)
How does it work?
- You write to the cache only.
- The cache asynchronously writes to the database later (in batches or after TTL).
Real-world analogy
You draft emails in your outbox, and they’re sent later when the connection is stable.
Pros
- Extremely fast writes
- Ideal for systems with write bursts
Cons
- Risk of data loss if the cache crashes before the DB write
- More complex logic and background syncing are required
.NET Consideration
You’ll need to implement a queue or background service that flushes the cache changes into the database periodically.
Write-Around
How does it work?
- Writes go only to the DB.
- Cache is updated only when data is read again (via cache-aside).
Real-world analogy
You restock your store shelves (cache) only when a customer asks and the item isn’t there.
Pros
- Keeps the cache clean
- Avoids polluting the cache with rarely-read data
Cons
- First read after a write = cache miss
- Potential for outdated cache
.NET Consideration
Simply avoid caching on write, but use cache-aside on read.
Tools You Can Use in .NET
- IMemoryCache (in-memory)
- IDistributedCache (Redis/SQL cache)
- StackExchange.Redis for advanced features
- LazyCache or CacheManager libraries for wrappers
- Hangfire for background flushing (write-back)
- Polly for caching with fallback and resilience
Conclusion
Caching is both an art and a science. The wrong strategy can give you stale data, write inconsistencies, or even app crashes. The right one? It’ll make your app fly.
Whether you’re working with APIs, distributed systems, or monoliths, understanding these caching strategies gives you the confidence to design apps that are fast, resilient, and scalable.
ASP.NET 10.0 Hosting Recommendation
ASP.NET is a powerful platform for creating web applications and services. You must be comfortable with JavaScript, HTML, CSS, and C# before developing a web application in ASP.NET. On the market, there are thousands of web hosting companies providing ASP.NET Hosting. But, only very few web hosting companies could provide high quality ASP.NET hosting solution.
ASP.NET is the best development language in Windows platform, which is released by Microsoft and widely used to build all types of dynamic Web sites and XML Web services. With this article, we’re going to help you to find the best ASP.NET Hosting solution in Europe based on reliability, features, price, performance and technical support. After we reviewed about 30+ ASP.NET hosting providers in Europe, our Best ASP.NET Hosting Award in Europe goes to HostForLIFE.eu, one of the fastest growing private companies and one of the most reliable hosting providers in Europe.