Implementing the Cache-Aside Pattern in .NET Core 9 with HybridCache
Boost .NET Core Performance with the Cache-Aside Pattern
Caching is one of the most effective strategies to improve the performance and scalability of your applications. But not all caching strategies are created equal. One of the most common patterns is the Cache-Aside (Lazy Loading) Pattern, which ensures your application only fetches data from the cache if available, otherwise loads it from the database and stores it in the cache for future requests.
In this article, we’ll explore how to implement the Cache-Aside pattern in .NET Core 9 using HybridCache, which supports both in-memory and Redis caching.
Why Cache-Aside?
The Cache-Aside pattern works like this:
Your application tries to read data from the cache.
If the data exists, return it immediately (cache hit).
If the data doesn’t exist (cache miss), fetch it from the database.
Store the fetched data in the cache for subsequent requests.
This approach is highly flexible because your cache doesn’t need to be kept in sync automatically with the database, it’s updated only when necessary.
Setting Up the Project
First, add the required NuGet packages for caching:
dotnet add package Microsoft.Extensions.Caching.Hybrid
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedisWe'll use HybridCache for managing cache across memory and Redis seamlessly.
Creating the Product Entity
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string SKU { get; set; }
}This is a simple Product entity for demonstration purposes.
Creating the Repository and Service Layer
We’ll define a repository interface to interact with the database and a service layer for caching logic.
IProductService.cs
using CacheStrategiesSample.Data;
using System.Collections.Generic;
using System.Threading.Tasks;
public interface IProductService
{
Task<Product?> GetByIdAsync(int id);
}ProductService.cs
using CacheStrategiesSample.Data;
using CacheStrategiesSample.Repository;
using Microsoft.Extensions.Caching.Hybrid;
using System.Collections.Generic;
using System.Threading.Tasks;
public class ProductService : IProductService
{
private readonly IRepository<Product> _productRepository;
private readonly HybridCache _cache;
public ProductService(IRepository<Product> productRepository, HybridCache cache)
{
_productRepository = productRepository;
_cache = cache;
}
public async Task<Product?> GetByIdAsync(int id)
{
string cacheKey = $"Product_{id}";
var product = await _cache.GetOrCreateAsync<Product?>(cacheKey, async _ =>
{
// Fetch from repository if not in cache
return await _productRepository.GetByIdAsync(id);
});
return product;
}
}Notice how the GetByIdAsync method handles caching. It first checks the cache and falls back to the repository if needed. This is the essence of the Cache-Aside pattern.
Creating the API Controller
using CacheStrategiesSample.Data;
using CacheStrategiesSample.Services;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var product = await _productService.GetByIdAsync(id);
if (product == null) return NotFound();
return Ok(product);
}
}With this setup, every request to GetById first checks the cache, reducing database load and improving response time.
Benefits of Using HybridCache
Seamless multi-level caching: In-memory + Redis.
Automatic key expiration: Avoid stale data.
Simple API:
GetOrCreateAsyncmakes cache-aside implementation almost trivial.Flexible storage: Switch or combine cache providers without changing business logic.
Conclusion
Implementing the Cache-Aside pattern in .NET Core 9 is straightforward with HybridCache. By combining repository-based data access with caching, you can dramatically improve your application’s performance, reduce database load, and maintain flexibility in your caching strategy.
This pattern is especially useful for high-traffic APIs where database hits are expensive and response speed matters.
🌟 Have you ever experienced a performance boost just by adding caching to your application? What strategy worked best for you?
👉 Full working code available at:
🔗https://sourcecode.kanaiyakatarmal.com/CacheStrategiesSample
I hope you found this guide helpful and informative.
Thanks for reading!
If you enjoyed this article, feel free to share it and follow me for more practical, developer-friendly content like this.


