Skip to content

Releases: jamesgober/dotnet-cache-kit

v1.0.0 — Initial Release

24 Feb 22:26

Choose a tag to compare

dotnet-cache-kit v1.0.0 Release

February 24, 2026

Welcome to v1.0.0!

We're pleased to announce the official v1.0.0 release of dotnet-cache-kit, a production-ready caching abstraction for .NET. After careful design, comprehensive testing, and thorough documentation, this release provides a stable, high-performance foundation for caching in any .NET application.

This is the first stable release — a clean, well-tested API you can depend on in production.

What is dotnet-cache-kit?

dotnet-cache-kit is a unified caching library built for modern .NET services. It provides a single API surface across memory and distributed backends, with built-in support for:

  • In-memory and distributed caching via a single ICacheKit interface
  • Stampede protection to prevent thundering herd on cold keys
  • Stale-while-revalidate for non-blocking cache refreshes
  • Absolute, sliding, and per-category TTL policies
  • Tag-based bulk invalidation
  • Pluggable serialization
  • Real-time cache metrics

Whether you're building APIs, background services, or high-throughput systems where cache misses are expensive, dotnet-cache-kit has you covered.

Key Features

Unified Cache API

One interface for every backend. Swap from in-memory to Redis without changing application code:

  • GetAsync / SetAsync — Basic cache operations
  • GetOrSetAsync — Cache-aside pattern with factory delegate
  • ExistsAsync — Key existence check without deserialization
  • RemoveAsync — Explicit key removal
  • InvalidateTagAsync / InvalidateTagsAsync — Bulk invalidation by tag

Stampede Protection

When a popular key expires, only one caller executes the factory. All other concurrent callers wait for the result instead of hammering the data source. Implemented via keyed semaphores with zero contention on different keys.

Stale-While-Revalidate

Serve the stale cached value immediately while refreshing in the background. Callers never block on a cache miss when stale data is available. Background refresh failures are logged without affecting the caller.

TTL Policies

Flexible expiration at every level:

  • Per-key — Set TTL, sliding expiration, or stale window on individual operations
  • Per-category — Define default options for groups of keys via AddCategoryDefaults
  • Global — Configure DefaultTtl, DefaultSlidingExpiration, and DefaultStaleTtl in CacheKitOptions

Precedence: per-key > category > global.

Tag-Based Invalidation

Associate cache entries with one or more tags, then invalidate all entries for a tag in a single call:

await cache.SetAsync("product:123", product, new CacheEntryOptions
{
    Tags = new[] { "products", "featured" }
});

// Later: remove all featured products from cache
await cache.InvalidateTagAsync("featured");

Pluggable Serialization

System.Text.Json is the default serializer. Swap it for MessagePack, Protobuf, or any custom implementation:

options.UseSerializer(new MyCustomSerializer());

Metrics

Track cache behavior in real time via cache.Metrics.Snapshot:

Counter Description
Hits Successful cache lookups
Misses Keys not found
StaleHits Stale values served during revalidation
Sets Write operations
Removals Explicit removals
Evictions Entries removed due to expiration
Size Current number of tracked entries

Installation

Install via NuGet:

dotnet add package JG.CacheKit

Or via Package Manager Console:

Install-Package JG.CacheKit

Quick Start

Register the cache:

builder.Services.AddCacheKit(options =>
{
    options.UseMemory();
    options.DefaultTtl = TimeSpan.FromMinutes(5);
    options.EnableStampedeProtection = true;
});

Use it:

public class ProductService(ICacheKit cache)
{
    public async Task<Product> GetProductAsync(string id) =>
        await cache.GetOrSetAsync(
            $"product:{id}",
            async ct => await LoadProductAsync(id, ct),
            new CacheEntryOptions { Ttl = TimeSpan.FromMinutes(10) });
}

For distributed backends like Redis, register an IDistributedCache and switch the provider:

services.AddStackExchangeRedisCache(o => o.Configuration = "localhost:6379");
services.AddCacheKit(options => options.UseDistributed());

See the API reference for full details.

What's in v1.0.0

This initial release includes the complete feature set:

Core API

  • ICacheKit interface with GetAsync, SetAsync, GetOrSetAsync, ExistsAsync, RemoveAsync
  • InvalidateTagAsync and InvalidateTagsAsync for tag-based bulk invalidation
  • ICacheMetrics with point-in-time CacheMetricsSnapshot

Providers

  • MemoryCacheProvider — In-memory storage via ConcurrentDictionary
  • DistributedCacheProvider — Any IDistributedCache backend (Redis, SQL Server, etc.)
  • ICacheProvider abstraction for custom implementations

Expiration

  • Absolute TTL, sliding expiration, and stale-while-revalidate windows
  • Per-key, per-category, and global default TTL policies
  • AddCategoryDefaults for category-level configuration

Serialization

  • JsonCacheSerializer (System.Text.Json) as the default
  • ICacheSerializer abstraction for custom implementations
  • Binary envelope format for distributed entries via CacheEnvelopeSerializer

Concurrency

  • Keyed semaphore stampede protection in GetOrSetAsync
  • Background refresh for stale-while-revalidate with LoggerMessage-based error logging
  • Thread-safe throughout: ConcurrentDictionary, Interlocked, SemaphoreSlim

DI Integration

  • Single AddCacheKit() registration
  • UseMemory(), UseDistributed(), UseProvider() provider selection
  • UseSerializer() for custom serialization
  • Options pattern with validation via PostConfigure

Input Validation

  • All public methods validate inputs (null keys, whitespace tags, negative TTLs)
  • CacheEntryOptions.Validate() enforces mutual exclusivity of TTL and sliding expiration
  • CacheKitOptions.Validate() enforces valid global defaults

Quality

Metric Value
Test count 46
Pass rate 100%
Compiler warnings 0
Known issues 0
Public API documentation Complete (XML docs with <exception> and <remarks>)
CI Multi-OS matrix (Ubuntu, Windows, macOS) with code coverage

Documentation

Community and Support

License

Licensed under the Apache License 2.0. See LICENSE for details.

Ready to get started? Install from NuGet and check out the API reference.


Full Changelog: https://github.com/jamesgober/dotnet-cache-kit/commits/v1.0.0