CoreSystem.Cache
3.0.0
See the version list below for details.
dotnet add package CoreSystem.Cache --version 3.0.0
NuGet\Install-Package CoreSystem.Cache -Version 3.0.0
<PackageReference Include="CoreSystem.Cache" Version="3.0.0" />
<PackageVersion Include="CoreSystem.Cache" Version="3.0.0" />
<PackageReference Include="CoreSystem.Cache" />
paket add CoreSystem.Cache --version 3.0.0
#r "nuget: CoreSystem.Cache, 3.0.0"
#:package CoreSystem.Cache@3.0.0
#addin nuget:?package=CoreSystem.Cache&version=3.0.0
#tool nuget:?package=CoreSystem.Cache&version=3.0.0
⚡ CoreSystem.Cache
Production-ready distributed caching framework for .NET 8
CoreSystem.Cache provides a unified cache abstraction with an execution pipeline, Memory caching, optional external cache storage with fallback, HTTP response caching, OpenTelemetry metrics, and tag-based invalidation.
✨ Features
- ✅ Memory cache provider
- ✅ Cache-Aside (
GetOrAddAsync) - ✅ Tag-based invalidation
- ✅ Optional external cache with Memory fallback
- ✅ HTTP response caching
- ✅ OpenTelemetry metrics for cache hits and misses
- ✅ Configurable execution pipeline
- ✅ Optional resilience integration through
Core.Resilience - ✅ Configurable serialization through
Core.Serialization
Redis support is provided by the CoreSystem.Cache.Redis package, which
registers Redis as the external primary storage and uses Memory as the
fallback storage.
📦 Installation
dotnet add package CoreSystem.Cache
For Redis support, add the Redis provider package separately:
dotnet add package CoreSystem.Cache.Redis
🚀 Quick Start
Register the framework:
builder.Services.AddCoreCache(options =>
{
options.InstanceName = "my-app";
});
Inject the cache service:
public sealed class ProductService(ICoreCache cache)
{
}
Store data:
await cache.SetAsync(
"products:1",
product,
TimeSpan.FromMinutes(10));
Retrieve data:
var product = await cache.GetAsync<Product>("products:1");
Recommended Cache-Aside pattern:
var product = await cache.GetOrAddAsync(
$"products:{id}",
async ct => await repository.GetByIdAsync(id, ct),
expiration: TimeSpan.FromMinutes(10),
tags: ["products"]);
🌐 HTTP Response Caching
Enable the middleware:
app.UseCoreCache();
Decorate your endpoint:
[Cacheable(expirationSeconds: 300)]
public async Task<IActionResult> Get(Guid id)
{
return Ok(await service.GetAsync(id));
}
HTTP response caching is applied only to endpoints decorated with
CacheableAttribute. The default request policy allows GET and HEAD
requests and excludes requests containing an Authorization header.
CacheOptions.DefaultExpiration sets the lifetime of a cached response when the
attribute omits expirationSeconds. It is not a fallback for SetAsync or
GetOrAddAsync: those operations store the entry with no expiration when the
expiration argument is null, so pass one explicitly when a lifetime is
needed.
📊 Why CoreSystem.Cache?
| Capability | IDistributedCache |
CoreSystem.Cache |
|---|---|---|
| Memory Provider | ❌ | ✅ |
| Cache-Aside | ❌ | ✅ |
| Tag Invalidation | ❌ | ✅ |
| Primary + Fallback Storage | ❌ | ✅ |
| HTTP Response Caching | ❌ | ✅ |
| OpenTelemetry Metrics | ❌ | ✅ |
| Configurable Cache Pipeline | ❌ | ✅ |
Redis and resilience capabilities are provided through their corresponding companion packages and are integrated with the cache pipeline when registered and configured.
🏗 Architecture
Application
│
▼
ICoreCache
│
▼
CachePipeline
│
├── Logging
├── Metrics
├── Fallback (when available)
└── Resilience (when registered)
│
▼
Cache Storage Resolver
│
├── External Storage (Primary)
│
└── Memory Storage (Fallback)
When no external cache storage is registered, Memory is used as the primary storage. When one external storage is registered, it becomes the primary storage and Memory becomes the fallback. The core resolver allows only one external cache storage to be registered.
📚 Documentation
The full documentation includes:
- Getting Started
- Architecture
- Configuration
- Basic Usage
- HTTP Response Caching
- Observability
- Health Checks
- Extensibility
- Roadmap
Visit the GitHub repository for the complete documentation.
🤝 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 was computed. 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 was computed. 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. |
-
net8.0
- CoreSystem.Http (>= 1.1.0)
- CoreSystem.Memory (>= 1.0.3)
- CoreSystem.Resilience (>= 2.0.1)
- CoreSystem.Serialization (>= 1.2.3)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on CoreSystem.Cache:
| Package | Downloads |
|---|---|
|
CoreSystem.Cache.Rehydration
Cache recovery component for CoreSystem.Cache on .NET 8, .NET 9 and .NET 10 that restores tracked memory fallback entries to the primary cache provider after recovery. |
|
|
CoreSystem.Cache.Redis
Redis external cache provider for CoreSystem.Cache on .NET 8, .NET 9 and .NET 10, with tag-based invalidation, distributed locking, health checks, and optional resilience integration. |
GitHub repositories
This package is not used by any popular GitHub repositories.
3.0.0: BREAKING CHANGES, two of them. (1) CacheOptions.MaxCacheableSize is removed. It was declared with a 1 MB default and copied by CopyFrom, but no cache storage ever read it, and it never did: it shipped dead. It also could not be implemented coherently, because Redis serializes first so a byte length is free, while the Memory provider stores the live object and never serializes, so measuring it would mean serializing every value purely to inspect it on the fastest path. A limit that binds for Redis users and silently does nothing for Memory users is a worse trap than no limit at all. Entries of any size are cached. Configure HTTP lifetime with DefaultExpiration and CacheableAttribute; for bounding memory use IMemoryCache.SizeLimit on the Memory provider or maxmemory-policy on the Redis server. (2) ICacheTagIndex<T>, MemoryKeyTracker and DefaultRequestCachePolicy are now internal. All three were public while the contract they implement is internal, so no consumer could substitute or implement them; a public type whose only interfaces are internal is not an extension point, only a wider API surface. ICacheTagIndex<T> was the last public member of Storage/Abstractions, and DefaultRequestCachePolicy now matches its sibling DefaultResponseCachePolicy, already internal sealed. The seams behind them are unchanged. MIGRATION: delete any assignment to MaxCacheableSize; reference IExternalCacheStorage instead of ICacheTagIndex<T>; remove any direct use of MemoryKeyTracker or DefaultRequestCachePolicy, all three being wired by the library at registration time. Nothing else changed. Dependency injection, the cache pipeline, Redis and Rehydration are unaffected, so 3.0.0 of CoreSystem.Cache.Redis and CoreSystem.Cache.Rehydration are released only to move their dependency onto this version.