Tyto.Caching
0.0.1-alpha.100
dotnet add package Tyto.Caching --version 0.0.1-alpha.100
NuGet\Install-Package Tyto.Caching -Version 0.0.1-alpha.100
<PackageReference Include="Tyto.Caching" Version="0.0.1-alpha.100" />
<PackageVersion Include="Tyto.Caching" Version="0.0.1-alpha.100" />
<PackageReference Include="Tyto.Caching" />
paket add Tyto.Caching --version 0.0.1-alpha.100
#r "nuget: Tyto.Caching, 0.0.1-alpha.100"
#:package Tyto.Caching@0.0.1-alpha.100
#addin nuget:?package=Tyto.Caching&version=0.0.1-alpha.100&prerelease
#tool nuget:?package=Tyto.Caching&version=0.0.1-alpha.100&prerelease
Tyto.Caching
Tyto.Caching is a modern, high-performance, and feature-rich distributed caching library for .NET. It is designed to handle complex caching scenarios with ease, offering multi-level caching (L1+L2), advanced stampede protection, Stale-While-Revalidate patterns, and event-driven auto-invalidation out of the box.
Focus on your business logic, and let Tyto handle the complexity of multi-layer synchronization, distributed locking, and cache consistency.
✨ Key Features
- Hybrid Multi-Level Caching (L1 + L2): Seamlessly combines ultra-fast local in-memory speed (L1) with distributed consistency (L2/Redis).
- Multi-Node L1 Synchronization (Backplane): Automatically broadcasts L1 invalidation messages across server clusters via lightweight pub/sub.
- Cache Stampede Protection: Prevents the "Thundering Herd" problem using distributed locks, ensuring only one factory executes per key across your cluster.
- Stale-While-Revalidate (SWR): Serves stale data instantly while refreshing the cache in the background. High availability, minimal latency.
- Event-Driven Auto-Invalidation: Declaratively evict cache entries directly within Tyto messaging endpoints when domain or integration events arrive.
- Smart Type-Safe Keys: Automatically generates collision-free keys formatted as
tyto:{ProfileName}:{TypeName}:{Key}. - Zero-Allocation Pooling: Uses
ObjectPoolfor cache execution contexts to minimize GC pressure under extreme throughput. - Full Observability: Built-in
System.Diagnosticsmetrics and OpenTelemetry tracing.
📦 Installation
Install the core package and the providers you need via NuGet:
dotnet add package Tyto.Caching
dotnet add package Tyto.Caching.Redis
dotnet add package Tyto.Caching.Memory
# Optional: Multi-node L1 sync & Distributed Locking
dotnet add package Tyto.Caching.Backplane
dotnet add package Tyto.Caching.Locking
🚀 Quick Start
1. Configure Services (Program.cs)
Caching is configured fluently inside the AddTyto container configuration:
var builder = WebApplication.CreateBuilder(args);
builder.AddTyto(tyto =>
{
tyto.AddDistributedCaching(caching =>
{
// 1. Register Providers (L1 Memory, L2 Redis)
caching.AddInMemoryProvider("LocalMem");
caching.AddRedisProvider("GlobalRedis", "localhost:6379");
// 2. Register Profiles (Smart defaults apply automatically)
caching.AddProfile<string, ProductDto>("ProductProfile", options =>
{
options.DefaultAbsoluteExpiration = TimeSpan.FromMinutes(30);
options.DefaultStaleWhileRevalidateAfter = TimeSpan.FromMinutes(2);
});
// Or register as .NET 8+ Keyed Service:
caching.AddKeyedProfile<int, OrderDto>("OrderProfile", options =>
{
options.DefaultAbsoluteExpiration = TimeSpan.FromHours(1);
});
});
});
2. Inject and Use in Application Code
Inject ICache<TKey, TValue> (or keyed service [FromKeyedServices("...")]) directly into your services:
public class ProductService(
ICache<string, ProductDto> cache,
ProductRepository repository)
{
public async Task<ProductDto?> GetProductAsync(string productId, CancellationToken ct)
{
// 1. Checks L1 -> 2. Checks L2 -> 3. Executes factory on miss -> 4. Populates L1 & L2
return await cache.GetOrSetAsync(productId, async () =>
{
return await repository.GetByIdAsync(productId, ct);
});
}
public async Task UpdatePriceAsync(string productId, decimal newPrice, CancellationToken ct)
{
await repository.UpdatePriceAsync(productId, newPrice, ct);
// Evicts key from L1 (Memory), L2 (Redis), and broadcasts via Backplane
await cache.InvalidateAsync(productId);
}
}
⚡ Event-Driven Cache Invalidation (InvalidateCache)
Eliminate boilerplate IEventHandler<T> classes written solely to clear cache entries. Bind domain/integration events directly to logical messaging endpoints:
builder.AddTyto(tyto =>
{
tyto.Endpoints(endpoints =>
{
endpoints.Add("CATALOG-EVENTS-EP", ep =>
{
// Listen on messaging queue
ep.ListenOn("rabbitmq", "q.catalog.events");
// 🎯 Auto-evict cache when specific events arrive:
ep.InvalidateCache<ProductDto>("ProductProfile")
.On<ProductPriceChangedEvent>(e => e.ProductId)
.On<ProductDeletedEvent>(e => e.ProductId)
.On<CategoryBulkUpdatedEvent>(e => e.AffectedProductIds); // Supports IEnumerable<string>
});
});
});
When an event arrives on this endpoint, the generic invalidator executes with zero GC allocation (Singleton), purges local and distributed layers, and notifies cluster replicas.
⚙️ Advanced Configuration
🛡️ Cache Stampede Protection (Distributed Locking)
Prevent thousands of concurrent requests from hitting your database simultaneously when a key expires:
caching.WithStampedeProtection();
📡 Multi-Node L1 Backplane Synchronization
Ensure that when Node 1 evicts a key, Node 2 and Node 3 instantly remove it from their local memory:
caching.WithBackplane();
🔄 Stale-While-Revalidate (Soft Expiration)
Return the stale cached value instantly and refresh it in the background without blocking the user:
var options = new CacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1), // Hard expiration (miss)
StaleWhileRevalidateAfter = TimeSpan.FromMinutes(5) // Soft expiration (background refresh)
};
await cache.GetOrSetAsync(key, factory, options);
🔑 Automatic Key Generation Standard
Tyto automatically constructs clean, human-readable, collision-free keys:
Redis / L1 Key = "tyto:{ProfileName}:{TypeName}:{Key}"
- Code:
cache.GetOrSetAsync("123", ...)forICache<string, List<ProductDto>>under"CatalogProfile" - Physical Key:
tyto:CatalogProfile:List[ProductDto]:123
📊 Observability
Tyto.Caching is fully instrumented with System.Diagnostics.Metrics and ActivitySource:
- Meter Name:
Tyto.Caching - Counters:
tyto.caching.hits.total(Tags:cache.profile_name,cache.layer=L1/L2)tyto.caching.misses.totaltyto.caching.sets.totaltyto.caching.invalidations.totaltyto.caching.backplane.messages.received.totaltyto.caching.get.duration(Histogram in seconds)
📝 API Reference
ICache<TKey, TValue>
| Method | Description |
|---|---|
GetOrSetAsync(key, factory, options) |
Primary entry point. Returns cached value or executes factory and sets cache. |
GetAsync(key) |
Returns the value if found, otherwise default. Does not trigger factory. |
TryGetAsync(key) |
Returns a CacheResult<TValue> struct (Hit, NegativeHit, or Miss). |
TryGet(key, out value) |
Synchronous fast-path check against the L1 (in-memory) layer only. |
SetAsync(key, value, options) |
Explicitly writes or updates a value across configured layers. |
InvalidateAsync(key) |
Removes the item from all configured layers (L1, L2, and Backplane broadcast). |
📄 License
This project is licensed under the MIT License.
| 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
- Tyto.Caching.Abstractions (>= 0.0.1-alpha.100)
- Tyto.Context (>= 0.0.1-alpha.100)
- Tyto.DependencyInjection (>= 0.0.1-alpha.100)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Tyto.Caching:
| Package | Downloads |
|---|---|
|
Tyto.Caching.Locking
Package Description |
|
|
Tyto.Caching.Redis
Package Description |
|
|
Tyto.Caching.Memory
Package Description |
|
|
Tyto.Caching.Backplane
Multi-node distributed L1 cache invalidation and synchronization support for Tyto.Caching. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.1-alpha.100 | 59 | 8/24/2026 |
| 0.0.1-alpha.99 | 84 | 8/20/2026 |
| 0.0.1-alpha.98 | 75 | 8/18/2026 |
| 0.0.1-alpha.97 | 79 | 8/18/2026 |
| 0.0.1-alpha.96 | 97 | 8/18/2026 |
| 0.0.1-alpha.95 | 70 | 8/17/2026 |
| 0.0.1-alpha.94 | 73 | 7/21/2026 |
| 0.0.1-alpha.93 | 69 | 7/20/2026 |
| 0.0.1-alpha.92 | 71 | 7/20/2026 |
| 0.0.1-alpha.91 | 84 | 6/11/2026 |
| 0.0.1-alpha.90 | 76 | 6/4/2026 |
| 0.0.1-alpha.89 | 76 | 6/4/2026 |
| 0.0.1-alpha.88 | 77 | 5/17/2026 |
| 0.0.1-alpha.87 | 85 | 5/17/2026 |
| 0.0.1-alpha.86 | 73 | 5/16/2026 |
| 0.0.1-alpha.85 | 72 | 5/16/2026 |
| 0.0.1-alpha.84 | 75 | 5/16/2026 |
| 0.0.1-alpha.83 | 73 | 5/16/2026 |
| 0.0.1-alpha.82 | 81 | 5/4/2026 |
| 0.0.1-alpha.81 | 73 | 5/4/2026 |