RepletoryLib.Caching.Hybrid
1.0.0
dotnet add package RepletoryLib.Caching.Hybrid --version 1.0.0
NuGet\Install-Package RepletoryLib.Caching.Hybrid -Version 1.0.0
<PackageReference Include="RepletoryLib.Caching.Hybrid" Version="1.0.0" />
<PackageVersion Include="RepletoryLib.Caching.Hybrid" Version="1.0.0" />
<PackageReference Include="RepletoryLib.Caching.Hybrid" />
paket add RepletoryLib.Caching.Hybrid --version 1.0.0
#r "nuget: RepletoryLib.Caching.Hybrid, 1.0.0"
#:package RepletoryLib.Caching.Hybrid@1.0.0
#addin nuget:?package=RepletoryLib.Caching.Hybrid&version=1.0.0
#tool nuget:?package=RepletoryLib.Caching.Hybrid&version=1.0.0
RepletoryLib.Caching.Hybrid
L1/L2 hybrid cache combining in-memory speed with Redis distributed consistency.
Part of the RepletoryLib ecosystem -- standalone, reusable .NET 10 libraries with zero business logic.
Overview
RepletoryLib.Caching.Hybrid implements ICacheService using a two-tier caching strategy:
- L1 (In-Memory) -- Ultra-fast, zero-latency local cache for hot data
- L2 (Redis) -- Distributed cache shared across all application instances
On a cache read, L1 is checked first. On a miss, L2 is checked and the result is promoted to L1. On a write or invalidation, both layers are updated and other instances are notified via Redis pub/sub to evict their L1 entries.
This gives you the speed of in-memory caching with the consistency of distributed caching.
Key Features
- Two-tier caching -- L1 (IMemoryCache) + L2 (Redis) with automatic promotion
- L1 invalidation via pub/sub -- Redis pub/sub notifies all instances when cache entries change
- Configurable TTLs -- Independent expiry for L1 and L2 layers
- Transparent -- Drop-in replacement for any
ICacheServiceimplementation
Installation
dotnet add package RepletoryLib.Caching.Hybrid
Or add to your .csproj:
<PackageReference Include="RepletoryLib.Caching.Hybrid" Version="1.0.0" />
Note: RepletoryLib packages are published to a local BaGet feed. See the main repository README for feed configuration.
Dependencies
| Package | Type |
|---|---|
RepletoryLib.Caching.InMemory |
RepletoryLib |
RepletoryLib.Caching.Redis |
RepletoryLib |
Prerequisites
- Redis 7+ running and accessible (for L2 and pub/sub)
docker-compose up -d redis
Quick Start
using RepletoryLib.Caching.Hybrid;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRepletoryHybridCache(builder.Configuration);
{
"RepletoryRedis": {
"ConnectionString": "localhost:6379",
"InstanceName": "myapp:",
"DefaultExpiryMinutes": 60
},
"RepletoryHybridCache": {
"L1ExpiryMinutes": 5,
"L2ExpiryMinutes": 60
}
}
Configuration
HybridCacheOptions
| Property | Type | Default | Description |
|---|---|---|---|
L1ExpiryMinutes |
int |
5 |
In-memory cache TTL (short-lived, local) |
L2ExpiryMinutes |
int |
60 |
Redis cache TTL (long-lived, distributed) |
Section name: "RepletoryHybridCache"
L1 expiry should always be shorter than L2. This ensures stale local data is naturally evicted even if a pub/sub message is missed.
Usage Examples
How It Works
GET "user:123"
├─ L1 (InMemory) HIT → return immediately (sub-microsecond)
└─ L1 MISS
├─ L2 (Redis) HIT → promote to L1, return
└─ L2 MISS
└─ Factory executes → store in L2, store in L1, return
SET "user:123"
├─ Store in L1 (local)
├─ Store in L2 (Redis)
└─ Publish invalidation via Redis pub/sub → other instances evict L1
REMOVE "user:123"
├─ Remove from L1 (local)
├─ Remove from L2 (Redis)
└─ Publish invalidation → other instances evict L1
Using the Hybrid Cache
using RepletoryLib.Caching.Abstractions.Interfaces;
public class ProductService
{
private readonly ICacheService _cache;
public ProductService(ICacheService cache) => _cache = cache;
public async Task<Product?> GetProductAsync(Guid id)
{
// First call: misses L1 and L2, loads from DB, caches in both
// Second call (same instance): hits L1, returns in <1ms
// Second call (different instance): hits L2, promotes to L1
return await _cache.GetOrSetAsync($"product:{id}", async () =>
{
return await _repository.GetByIdAsync(id);
});
}
public async Task UpdateProductAsync(Product product)
{
await _repository.UpdateAsync(product);
// Removes from L1, L2, and notifies other instances
await _cache.RemoveAsync($"product:{product.Id}");
}
}
When to Use Hybrid vs Redis-Only
| Scenario | Recommendation |
|---|---|
| Frequently read, rarely updated | Hybrid (L1 absorbs most reads) |
| Frequently updated data | Redis-only (L1 invalidation overhead not worth it) |
| Single instance | InMemory or Hybrid (both fast, Hybrid adds Redis durability) |
| Multiple instances, read-heavy | Hybrid (best performance) |
| Multiple instances, write-heavy | Redis-only |
Integration with Other RepletoryLib Packages
| Package | Relationship |
|---|---|
RepletoryLib.Caching.Abstractions |
Implements ICacheService |
RepletoryLib.Caching.InMemory |
Provides the L1 layer |
RepletoryLib.Caching.Redis |
Provides the L2 layer and pub/sub |
RepletoryLib.Auth.Jwt |
Token blacklist benefits from hybrid speed |
Troubleshooting
| Issue | Solution |
|---|---|
| L1 cache returns stale data | Check Redis connectivity -- pub/sub invalidation requires an active Redis connection |
| Performance not better than Redis | Ensure L1 TTL is long enough for your access patterns. Very short L1 TTL negates the benefit. |
| Memory growing on L1 | Reduce L1ExpiryMinutes. L1 entries are evicted by both TTL and memory pressure. |
License
This project is licensed under the MIT License.
Copyright (c) 2024-2026 Repletory.
For complete documentation, infrastructure setup, and configuration reference, see the RepletoryLib main repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.0)
- RepletoryLib.Caching.InMemory (>= 1.0.0)
- RepletoryLib.Caching.Redis (>= 1.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 76 | 3/2/2026 |