HybridCache in .NET 9 is Awesome!

.NET 9 is now live, and it comes with a new set of features. Some are great, and some are just icing on the cake. But what really stands out is the new HybridCache!

HybridCache is not just another caching API in .NET; it’s designed to solve problems we didn’t even know we had. It combines the best of two worlds by bridging the gap between IMemoryCache and IDistributedCache. It also introduces advanced features like cache stampede protection and efficient serialization.

In this blog, I’m going to review the existing caching mechanisms, highlight their strengths and weaknesses, and demonstrate how to implement the new HybridCache. We’ll see how it simplifies caching and makes it incredibly easy to use.

Download the source code from here

You can also watch my YouTube video on the same topic here: https://youtu.be/PDIKTbbkmCk

Understanding Existing Caching Mechanisms

IMemoryCache

The IMemoryCache provides fast, in-memory caching within the application’s process. It has also few limitations, such as the cache is limited to only a single instance and data is lost if the application restarts or craches.

IDistributedCache

In the other hand, IDistributedCache offers a caching mechanism that can be shared across multiple instances, giving you the ability to preserve and distribute cache data across your distributed system. And as for the drawbacks, accessing the distributed cache can be slower than the in-memory cache due to network overhead, and it does require additional setup and configuration.

Introducting HybridCache

HybridCache in .NET 9 combines both IMemoryCache and IDistributedCache, providing a unified API that leverages a two level caching strategy:

  1. Primary Cache (L1): In-memory cache for fast access.
  2. Secondary Cache (L2): Distributed cache for scalability and persistance

HybridCache comes with some interesting features, one of which is the cache stampede protenction, where it prevents multiple concurrent requests from overwhelming the data source by ensuring only one request populate the cache for a given key.

It also support various serialization options, making it a serialization optimized solution where you can chose the right option for your application.

And my favorite option is, the tag based invalidation, where it enables you to invalidate a group of cache entries related to a specific tag for efficient invalidations.

Implementing HybridCache

First, you need to install the nuget package

dotnet add package Microsoft.Extensions.Caching.Hybrid --version "X.X.X" # add the latest version here

Then you need to register the HybridCache inside your DI

// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddHybridCache();

You can also configure options such as serialization and cache entry settings:

builder.Services.AddHybridCache(options =>
{
    options.MaximumPayloadBytes = 1024 * 1024; // 1 MB
    options.MaximumKeyLength = 1024;
    options.DefaultEntryOptions = new HybridCacheEntryOptions
    {
        Expiration = TimeSpan.FromMinutes(5),
        LocalCacheExpiration = TimeSpan.FromMinutes(5)
    };
});

And to use it in your application, simply inject the HybridCache into your service or endpoint and use it to cache data:

public class BookService
{
    private readonly HybridCache _hybridCache;
    public BookService(HybridCache hybridCache)
    {
        _hybridCache = hybridCache;
    }
    
    public async Task<Book?> GetBookAsync(int id)
    {
        var key = $"book-{id}";
        
        return await _hybridCache.GetOrCreateAsync(key, async (cancellation) =>
        {
            // Get the book from the database
        });

You can also use _hybridCache.SetAsync to set the cache directly.

public async Task<Book?> UpdateYearAsync(int id, int year)
{
    var book = await _context.Books.FindAsync(id);
    if (book is null) return null;
    
    book.Year = year;
    await _context.SaveChangesAsync();
    await _hybridCache.SetAsync($"book-{id}", book);
    
    return book;
}

Or you can use _hybridCache.RemoveAsync to remove and invalidate a cache entry

await _hybridCache.RemoveAsync($"book-{id}");

HybridCache in .NET 9 offers a robust solution for caching by combining the speed of in-memory access with the scalability of distributed caching. Its advanced features like stampede protection and configurable serialization make it a valuable addition to any .NET application.

Happy Coding!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.