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) │ │ │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────┘
| Layer | Speed | Shared across servers? | Survives restart? |
|---|---|---|---|
| IMemoryCache (L1) | Fastest | No | No |
| Redis (L2) | Fast | Yes | Yes |
| HybridCache | Best of both | Yes | Yes (L2) |
Quick Comparison
| IMemoryCache | Redis only | HybridCache | |
|---|---|---|---|
| Local speed | Excellent | Network hop | Excellent (L1) |
| Multi-server | Diverges | Consistent | Consistent |
| Stampede protection | Manual | Manual | Built-in |
| Code complexity | Low | Medium | Low |
| .NET version | Long time | Long 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)
| Scenario | Recommendation |
|---|---|
| Local dev / single instance | IMemoryCache or HybridCache (no Redis) |
| Web farm / Container Apps | HybridCache + Redis |
| SQLite desktop / offline app | IMemoryCache (or HybridCache L1) |
| High consistency required | Redis as L2 |
Other Alternatives
| Option | Notes |
|---|---|
| IMemoryCache | Simplest. Per-process only. |
| IDistributedCache (Redis) | Shared, but every call is network. |
| HybridCache | Best default in .NET 9+. |
| FusionCache | Popular 3rd-party. More features (fail-safe, soft timeouts). |
| LazyCache | Older, simple wrapper over IMemoryCache. |
| SQLite as cache | Possible 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!