Tyto.Caching 0.0.1-alpha.100

This is a prerelease version of Tyto.Caching.
dotnet add package Tyto.Caching --version 0.0.1-alpha.100
                    
NuGet\Install-Package Tyto.Caching -Version 0.0.1-alpha.100
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Tyto.Caching" Version="0.0.1-alpha.100" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Tyto.Caching" Version="0.0.1-alpha.100" />
                    
Directory.Packages.props
<PackageReference Include="Tyto.Caching" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Tyto.Caching --version 0.0.1-alpha.100
                    
#r "nuget: Tyto.Caching, 0.0.1-alpha.100"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Tyto.Caching@0.0.1-alpha.100
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Tyto.Caching&version=0.0.1-alpha.100&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Tyto.Caching&version=0.0.1-alpha.100&prerelease
                    
Install as a Cake Tool

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 ObjectPool for cache execution contexts to minimize GC pressure under extreme throughput.
  • Full Observability: Built-in System.Diagnostics metrics 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", ...) for ICache<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.total
    • tyto.caching.sets.total
    • tyto.caching.invalidations.total
    • tyto.caching.backplane.messages.received.total
    • tyto.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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed