GB.
2025-08-124 min read

HybridCache + Redis vs IMemoryCache

#HybridCache#Redis#IMemoryCache#Caching#.NET 9#SQLite

HybridCache + Redis vs IMemoryCache

Caching is simple until you have more than one server.

One server                     Multiple servers
───────────                    ────────────────
IMemoryCache                   ??? 
(fast, local)                  (local caches diverge)

HybridCache (.NET 9) solves this cleanly.


The Three Layers

┌─────────────────────────────────────┐
│           HybridCache               │
│  ┌─────────────┐   ┌─────────────┐  │
│  │ IMemoryCache│ + │  Redis (L2) │  │
│  │    (L1)     │   │             │  │
│  └─────────────┘   └─────────────┘  │
└─────────────────────────────────────┘
LayerSpeedShared across servers?Survives restart?
IMemoryCache (L1)FastestNoNo
Redis (L2)FastYesYes
HybridCacheBest of bothYesYes (L2)

Quick Comparison

IMemoryCacheRedis onlyHybridCache
Local speedExcellentNetwork hopExcellent (L1)
Multi-serverDivergesConsistentConsistent
Stampede protectionManualManualBuilt-in
Code complexityLowMediumLow
.NET versionLong timeLong time.NET 9+

How HybridCache Works

Get "product:42"
        │
        ▼
   L1 (Memory)? ──yes──▶ return
        │ no
        ▼
   L2 (Redis)?  ──yes──▶ store in L1 → return
        │ no
        ▼
   Factory (DB) ──▶ store L1 + L2 → return

One API. L1 + L2 + stampede protection.


Minimal Setup

// Program.cs
builder.Services.AddHybridCache();

// Optional: use Redis as L2
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "localhost:6379";
});
public class ProductService(HybridCache cache, AppDbContext db)
{
    public async Task<Product?> GetAsync(int id, CancellationToken ct = default)
    {
        return await cache.GetOrCreateAsync(
            $"product:{id}",
            async token => await db.Products.FindAsync([id], token),
            cancellationToken: ct);
    }
}

That’s it.


Does It Fit with SQLite?

Yes - they solve different problems.

SQLite          →  persistent relational data
HybridCache     →  fast temporary cache in front of data

Common pattern:

Request
   │
   ▼
HybridCache (L1 memory + optional L2 Redis)
   │ miss
   ▼
SQLite (or SQL Server)

You can even run HybridCache with only L1 (no Redis) for single-instance apps that still use SQLite.

// No Redis registered → HybridCache uses memory only
builder.Services.AddHybridCache();

When to Use What

Single server / desktop / simple API?
        │
        ▼
IMemoryCache  or  HybridCache (L1 only)

Multiple servers / containers?
        │
        ▼
HybridCache + Redis

Need cache to survive restarts + shared?
        │
        ▼
Redis (via HybridCache or IDistributedCache)
ScenarioRecommendation
Local dev / single instanceIMemoryCache or HybridCache (no Redis)
Web farm / Container AppsHybridCache + Redis
SQLite desktop / offline appIMemoryCache (or HybridCache L1)
High consistency requiredRedis as L2

Other Alternatives

OptionNotes
IMemoryCacheSimplest. Per-process only.
IDistributedCache (Redis)Shared, but every call is network.
HybridCacheBest default in .NET 9+.
FusionCachePopular 3rd-party. More features (fail-safe, soft timeouts).
LazyCacheOlder, simple wrapper over IMemoryCache.
SQLite as cachePossible but unusual. Better as primary store.

Final Takeaway

IMemoryCache     →  fast, local, simple
Redis            →  shared, durable
HybridCache      →  fast + shared (L1 + L2)

Start with HybridCache.
Add Redis when you actually have more than one instance.

SQLite and HybridCache work well together:
SQLite holds the data, HybridCache makes the hot paths fast.

Enjoyed this article? Share it with your network!