
How to Implement HybridCache in .NET using C# – A Better Caching Strategy
Introduction
After covering essential caching concepts in my article about in-memory caching and exploring distributed solutions with Redis caching, it’s time to discover a powerful new approach that combines the best of both worlds: HybridCache.
The .NET team has introduced HybridCache as an innovative solution that addresses common caching challenges. This new caching strategy intelligently combines in-memory caching’s speed with distributed caching’s scalability, offering a more robust and efficient caching mechanism for modern applications.
In this article, I’ll demonstrate how to implement HybridCache in your .NET applications. You’ll learn how this hybrid approach provides:
- In-process caching for maximum performance
- Distributed caching capabilities for scalability
- Automatic stampede protection to prevent cache overload
- Smart instance reuse for optimized memory usage
Whether you’re building a small application or a large-scale distributed system, understanding HybridCache will help you make better decisions about your caching strategy. Let’s explore how this new caching solution can enhance your application’s performance while simplifying your caching implementation.
Core Features of HybridCache
- Unified Two-Level Caching
- Combines in-memory and distributed caching in a single API
- Automatically manages data synchronization between cache levels
- Provides seamless fallback mechanisms if one cache level fails
- Smart Cache Management
- Stampede Protection: Prevents multiple concurrent requests from overwhelming the system
- Configurable Expiration: Separate control for local and distributed cache expiration
- Tag-Based Invalidation: Group related cache entries for bulk operations
- Advanced Serialization
- Built-in support for
string
andbyte[]
types - Default
System.Text.Json
serialization for complex objects - Extensible architecture supporting custom serializers (Protobuf, XML)
- Developer-Friendly API
// Simple implementation example
public class WeatherService
{
private readonly HybridCache _cache;
public async Task<WeatherData> GetWeatherAsync(string city)
{
return await _cache.GetOrCreateAsync(
$"weather_{city}",
async _ => await FetchWeatherDataAsync(city),
new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromHours(1),
LocalCacheExpiration = TimeSpan.FromMinutes(5)
}
);
}
}
- Performance Optimizations
- Instance reuse for immutable objects
- Efficient memory usage through configurable size limits
- Optimized byte allocation handling
- Enterprise-Ready Features
- Built-in monitoring and logging
- Configurable maximum payload size
- Flexible key management with validation
By providing these features in a single, cohesive API, HybridCache simplifies caching implementation while offering powerful capabilities that previously required complex custom solutions.
Key Benefits:
- Reduced development complexity
- Better performance through optimized caching strategies
- Improved scalability with distributed caching support
- Enhanced reliability with automatic fallback mechanisms
This modern approach to caching addresses common challenges in distributed systems while maintaining simplicity for developers.
Example: How to Use IMemoryCache with Minimal API and .NET
Disclaimer: This example is purely for educational purposes. There are better ways to write code and applications that can optimize this example. Use this as a starting point for learning, but always strive to follow best practices and improve your implementation.
All the code is available in this GitHub repository and use the hybrid branch . This repository will help you easily apply the new modifications to the previously created code thanks to the use of tags and branches.
Prerequisites
Before starting, make sure you have the following installed:
- .NET SDK: Download and install the .NET SDK if you haven’t already.
- Visual Studio Code (VSCode): Install Visual Studio Code for a lightweight code editor.
- C# Extension for VSCode: Install the C# extension for VSCode to enable C# support.
- Docker Client: Install Docker Desktop.
Clone the Repository:
Clone the WebApiCachingInMemory Repository using the web URL
https://github.com/ottorinobruni/WebApiCachingInMemory.git

Install Necessary Library:
Install the Microsoft.Extensions.Caching.Hybrid package.
dotnet add package Microsoft.Extensions.Caching.Hybrid

You can run Redis locally using Docker with the following command:
docker run --name my-redis -p 6379:6379 -d redis
Redis comes with a CLI tool (redis-cli) that you can use to interact with it. Let’s test if it’s working fine:
docker exec -it my-redis redis-cli
You can then run commands like:
ping # Test if Redis is running
set mykey "Hello World" # Set a key
get mykey # Retrieve the value

Modify UserService to use HybridCache
We need to change the caching logic to work with HybridCache.
using Microsoft.Extensions.Caching.Hybrid;
public interface IUserService
{
Task<List<User>> GetUsers();
}
public class UserService : IUserService
{
private readonly HybridCache _hybridCache;
private const string cacheKey = "users";
public UserService(HybridCache hybridCache)
{
this._hybridCache = hybridCache;
}
public async Task<List<User>> GetUsers()
{
Console.WriteLine("GetUsers method called.");
var users = await _hybridCache.GetOrCreateAsync(cacheKey,
async _ => {
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Cache miss. Fetching data from the database.");
return await GetValuesFromDbAsync();
});
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Data retrieved from the cache.");
return users;
}
private async Task<List<User>> GetValuesFromDbAsync()
{
List<User> users = new List<User>
{
new User { Id = 1, Name = "Alice" },
new User { Id = 2, Name = "Bob" },
new User { Id = 3, Name = "Otto" },
};
// Simulating a long-running database query.
await Task.Delay(2000);
return users;
}
}

Register HybridCache as the Cache Provider in Program.cs
Now, we need to update the DI container to use HybridCache
in our Program.cs
file.
using Microsoft.Extensions.Caching.Hybrid;
var builder = WebApplication.CreateBuilder(args);
// Add HybridCache with Redis as distributed cache
builder.Services.AddHybridCache(options =>
{
options.DefaultEntryOptions = new HybridCacheEntryOptions
{
Expiration = TimeSpan.FromMinutes(2),
LocalCacheExpiration = TimeSpan.FromMinutes(1)
};
});
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
options.InstanceName = "my-redis";
});
builder.Services.AddScoped<IUserService, UserService>(); // Register UserService
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
//app.UseHttpsRedirection();
app.MapGet("/users", async (IUserService userService) =>
{
var users = await userService.GetUsers();
return Results.Ok(users);
})
.WithName("GetUsers")
.WithOpenApi();
app.Run();

HybridCache Implementation Benefits
Two-Tier Caching Architecture
- Fast in-memory primary cache (1 min expiration)
- Redis-based distributed secondary cache (2 min expiration)
- Automatic synchronization between tiers
Developer-Friendly Features
await _hybridCache.GetOrCreateAsync(cacheKey,
async _ => await GetValuesFromDbAsync());
- Single API for both cache levels
- Built-in serialization
- Automatic cache management
- Real-time operation logging
Performance & Scalability
- Optimized memory usage
- Automatic stampede protection
- Seamless distributed caching
- Cloud-ready configuration
This implementation delivers robust caching with significantly less code than traditional separate memory/Redis solutions.

Conclusion
HybridCache represents a significant evolution in .NET caching strategies, marking a substantial improvement over traditional caching approaches. By combining the speed of in-memory caching with the reliability of distributed cache systems like Redis, it offers developers a powerful yet simplified solution for modern applications.
The most striking advantage is the dramatic reduction in code complexity – gone are the days of managing multiple cache implementations, handling serialization manually, or writing complex fallback logic. Instead, HybridCache provides a single, unified API that handles all these aspects automatically, while also incorporating advanced features like stampede protection and intelligent cache-level management. This streamlined approach not only makes the code more maintainable but also reduces the potential for errors and improves overall system reliability. The implementation offers comprehensive logging capabilities that make debugging and monitoring cache behavior straightforward, providing clear visibility into cache operations without additional complexity.
Notably, HybridCache maintains broad compatibility across the .NET ecosystem, supporting .NET Framework 4.7.2 and later, as well as .NET Standard 2.0, making it a viable solution for both new and existing projects.
It’s worth mentioning that at the time of writing this article (April 2024), there’s a known compatibility issue with Microsoft.Extensions.Caching.StackExchangeRedis version 9.0.3, which is why this implementation uses version 9.0.2 – a practical consideration for developers implementing this solution.
Whether you’re developing a small application or a large-scale distributed system, HybridCache provides an efficient, scalable, and maintainable caching strategy that significantly reduces development complexity while delivering enterprise-grade features. This modern approach to caching demonstrates how far we’ve come in simplifying complex technical challenges while improving overall system performance and reliability.
If you think your friends or network would find this article useful, please consider sharing it with them. Your support is greatly appreciated.
Thanks for reading!
Discover CodeSwissKnife, your all-in-one, offline toolkit for developers!
Click to explore CodeSwissKnife
myles
RemoveByTagAsync doesn’t appear to work in version 9.3.0
Ottorino Bruni
Sorry I don’t understand your point, it exists in the documentation. https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.hybrid.hybridcache.removebytagasync?view=net-9.0-pp