CoreSystem.Cache.Redis
2.2.0
dotnet add package CoreSystem.Cache.Redis --version 2.2.0
NuGet\Install-Package CoreSystem.Cache.Redis -Version 2.2.0
<PackageReference Include="CoreSystem.Cache.Redis" Version="2.2.0" />
<PackageVersion Include="CoreSystem.Cache.Redis" Version="2.2.0" />
<PackageReference Include="CoreSystem.Cache.Redis" />
paket add CoreSystem.Cache.Redis --version 2.2.0
#r "nuget: CoreSystem.Cache.Redis, 2.2.0"
#:package CoreSystem.Cache.Redis@2.2.0
#addin nuget:?package=CoreSystem.Cache.Redis&version=2.2.0
#tool nuget:?package=CoreSystem.Cache.Redis&version=2.2.0
⚡ CoreSystem.Cache.Redis
Redis distributed cache provider for CoreSystem.Cache on .NET 8, 9 and 10
CoreSystem.Cache.Redis registers Redis as the external primary cache storage
for CoreSystem.Cache. Memory caching becomes the automatic fallback, so cache
reads keep working while Redis is unreachable.
The package targets .NET 8, .NET 9 and .NET 10, and ships an assembly for each of those frameworks.
The package does not implement a cache API. Application services continue to use
ICoreCache exactly as they do with the core package.
✨ Features
- ✅ Redis as the external primary cache storage
- ✅ Automatic Memory fallback when Redis is unavailable
- ✅ Tag-based invalidation through a Redis tag index
- ✅ Distributed locking for concurrent cache population
- ✅ Health check reported as
redis_cache, taggedcacheandprimary - ✅ Optional resilience integration through
CoreSystem.Resilience - ✅ Configurable serialization through
Core.Serialization
📦 Installation
Install the core package first, then the Redis provider:
dotnet add package CoreSystem.Cache
dotnet add package CoreSystem.Cache.Redis
| Package | Responsibility |
|---|---|
| CoreSystem.Cache | Cache orchestration, storage resolution and fallback support |
| CoreSystem.Cache.Redis | Redis as the external primary storage, with Memory as the fallback |
| CoreSystem.Cache.Rehydration | Recovery of tracked fallback entries into the primary storage |
🚀 Quick Start
Register the core cache first. AddCoreCacheRedis() reads the CacheOptions
instance registered here, so the order matters:
builder.Services.AddCoreCache(options =>
{
options.InstanceName = "my-app";
});
Then register Redis:
builder.Services.AddCoreCacheRedis(options =>
{
options.Configuration = redis =>
{
redis.EndPoints.Add("localhost", 6379);
};
});
The Configuration delegate receives the StackExchange.Redis
ConfigurationOptions, so any connection setting is available.
Add health checks so the redis_cache check is registered:
builder.Services.AddHealthChecks();
Application services keep using ICoreCache:
public sealed class ProductService(ICoreCache cache)
{
public Task<Product?> GetAsync(
string key,
CancellationToken ct = default)
=> cache.GetAsync<Product>(key, ct);
}
Cache-Aside reads work unchanged:
var product = await cache.GetOrAddAsync(
$"products:{id}",
async ct => await repository.GetByIdAsync(id, ct),
expiration: TimeSpan.FromMinutes(10),
tags: ["products"]);
⚠️ Registration Requirements
AddCoreCacheRedis() throws InvalidOperationException when:
AddCoreCache()has not been called, because noCacheOptionsinstance is registered (CacheRedisRegistration.cs:139);- the
Configurationdelegate did not assignConfiguration(CacheRedisRegistration.cs:124).
When the core cache is registered but disabled (CacheOptions.Enabled is
false), the Redis services are not registered and no exception is thrown.
🔑 Key Prefixing
CacheOptions.InstanceName is used as a Redis key prefix. The provider appends
its own separator, so do not add a trailing colon:
options.InstanceName = "my-app";
produces keys such as:
my-app:products:1
If no instance name is configured, no prefix is added. The Memory storage does not apply this prefix.
❤️ Health Checks
The provider registers a health check named redis_cache with the tags cache
and primary. The primary tag is what
CoreSystem.Cache.Rehydration observes to detect a recovery.
The check reports:
| Result | Description |
|---|---|
| Healthy | Redis is connected successfully. |
| Degraded | Redis is not responding. Memory fallback active. |
The check is contributed through an IHealthCheckContributor, so
AddHealthChecks() must be called for it to be registered.
🔁 Fallback and Locking
Registering the provider enables the fallback behavior automatically, so the storage resolver resolves Redis as primary and Memory as fallback.
GetOrAddAsync acquires a distributed lock per key before populating the entry,
then re-reads the value inside the lock. This prevents several instances from
populating the same key concurrently.
🛡 Resilience
CoreSystem.Resilience defines a dedicated PipelineType.Redis. When a Redis
resilience pipeline is configured, the provider adds the following exceptions to
the Retry and Circuit Breaker handling:
RedisConnectionExceptionRedisTimeoutExceptionTimeoutException
The strategies and their options belong to CoreSystem.Resilience, not to
RedisOptions, which exposes only Configuration.
🏗 Architecture
ICoreCache
│
▼
CachePipeline
│
├── Logging
├── Metrics
├── Fallback (enabled by the Redis provider)
└── Resilience (when a Redis pipeline is configured)
│
▼
Cache Storage Resolver
│
├── RedisCacheStorage (Primary)
│
└── Memory Storage (Fallback)
📚 Documentation
The full documentation covers:
- Getting Started
- Architecture
- Configuration
- Basic Usage
- Health Checks
- Extensibility
- Roadmap
Visit federin.github.io/CoreSystem.Cache/Redis for the complete reference.
🤝 Contributing
Issues, discussions and pull requests are welcome.
📄 License
Released under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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
- CoreSystem.Cache (>= 3.1.0)
- CoreSystem.Cache.Rehydration (>= 2.2.0)
- CoreSystem.Http (>= 1.2.0)
- CoreSystem.Memory (>= 1.1.0)
- CoreSystem.Redis (>= 1.1.0)
- CoreSystem.Resilience (>= 2.1.0)
- CoreSystem.Serialization (>= 1.3.0)
-
net8.0
- CoreSystem.Cache (>= 3.1.0)
- CoreSystem.Cache.Rehydration (>= 2.2.0)
- CoreSystem.Http (>= 1.2.0)
- CoreSystem.Memory (>= 1.1.0)
- CoreSystem.Redis (>= 1.1.0)
- CoreSystem.Resilience (>= 2.1.0)
- CoreSystem.Serialization (>= 1.3.0)
-
net9.0
- CoreSystem.Cache (>= 3.1.0)
- CoreSystem.Cache.Rehydration (>= 2.2.0)
- CoreSystem.Http (>= 1.2.0)
- CoreSystem.Memory (>= 1.1.0)
- CoreSystem.Redis (>= 1.1.0)
- CoreSystem.Resilience (>= 2.1.0)
- CoreSystem.Serialization (>= 1.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
2.2.0: Multi-targeting release. The package now ships net8.0, net9.0 and net10.0 assets instead of net8.0 only. Depends on CoreSystem.Cache.Rehydration 2.1.3 and on CoreSystem.Redis 1.1.0, which carries StackExchange.Redis 2.13.17. The cross-repo dependencies are refreshed to CoreSystem.Http 1.2.0, CoreSystem.Memory 1.1.0, CoreSystem.Resilience 2.1.0 and CoreSystem.Serialization 1.3.0, which is what removes the NU1605 restore failure on net10.0 described in 2.1.3: earlier Resilience versions constrained Microsoft.Extensions.* to 8.0.x while OpenTelemetry asks for 10.0.0. Verified with real net8.0, net9.0 and net10.0 consumer projects: all three restore and resolve with no workaround. This build still declares CoreSystem.Cache.Rehydration 2.1.3 and CoreSystem.Cache 3.0.2 because those are the versions on the feed while it is prepared; the pins move to 2.2.0 and 3.1.0 once those versions are published. No public API changed, nothing is renamed and no code changed. AddCoreCacheRedis behaves exactly as in 2.1.3. The AddHealthChecks() prerequisite still applies: without it the redis_cache health check is never registered and rehydration cannot observe a recovery.