services.AddCacheKit(options =>
{
options.UseMemory();
options.DefaultTtl = TimeSpan.FromMinutes(5);
options.EnableStampedeProtection = true;
options.EnableStaleWhileRevalidate = true;
});| Method | Description |
|---|---|
UseMemory() |
In-memory cache (default). Suitable for single-instance deployments. |
UseDistributed() |
Uses a registered IDistributedCache (Redis, SQL Server, etc.). |
UseProvider(factory) |
Registers a custom ICacheProvider implementation. |
Register a distributed cache before calling AddCacheKit:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
});
services.AddCacheKit(options => options.UseDistributed());The default serializer uses System.Text.Json. To use a custom serializer:
options.UseSerializer(new MyCustomSerializer());
// or
options.UseSerializer(sp => sp.GetRequiredService<MySerializer>());Custom serializers implement ICacheSerializer:
public interface ICacheSerializer
{
byte[] Serialize<T>(T value);
T? Deserialize<T>(ReadOnlyMemory<byte> payload);
}All methods accept an optional CancellationToken.
Returns the cached value for a key, or default if not found or expired.
var product = await cache.GetAsync<Product>("product:123");Returns true if a key exists and has not expired.
if (await cache.ExistsAsync("product:123"))
{
// key is present
}Stores a value with optional per-entry configuration.
await cache.SetAsync("product:123", product, new CacheEntryOptions
{
Ttl = TimeSpan.FromMinutes(10),
Tags = new[] { "products" }
});Returns the cached value or invokes the factory to populate it. Stampede protection ensures only one caller executes the factory for a given key.
var product = await cache.GetOrSetAsync(
"product:123",
async ct => await db.Products.FindAsync(id, ct),
new CacheEntryOptions { Ttl = TimeSpan.FromMinutes(10) });Removes a cached entry by key. Idempotent — removing a non-existent key is a no-op.
await cache.RemoveAsync("product:123");Removes all entries associated with one or more tags.
await cache.InvalidateTagAsync("products");
await cache.InvalidateTagsAsync(new[] { "products", "featured" });Per-entry configuration passed to SetAsync and GetOrSetAsync.
| Property | Type | Description |
|---|---|---|
Ttl |
TimeSpan? |
Absolute time-to-live. |
SlidingExpiration |
TimeSpan? |
Sliding expiration window. Mutually exclusive with Ttl. |
StaleTtl |
TimeSpan? |
Duration after expiration during which stale data is served while refreshing. |
Tags |
IReadOnlyCollection<string>? |
Tags for bulk invalidation. |
Category |
string? |
Category name for resolving per-category defaults. |
Global defaults configured via AddCacheKit.
| Property | Type | Default | Description |
|---|---|---|---|
DefaultTtl |
TimeSpan |
5 minutes | Default TTL when no per-entry TTL is specified. |
DefaultSlidingExpiration |
TimeSpan? |
null |
Default sliding expiration. |
DefaultStaleTtl |
TimeSpan? |
null |
Default stale window. |
EnableStampedeProtection |
bool |
true |
Lock-based cache population to prevent thundering herd. |
EnableStaleWhileRevalidate |
bool |
true |
Serve stale data while refreshing in the background. |
TimeProvider |
TimeProvider |
TimeProvider.System |
Clock used for expiration. Override for testing. |
Define default options for groups of cache entries:
options.AddCategoryDefaults("products", new CacheEntryOptions
{
Ttl = TimeSpan.FromMinutes(30)
});Then reference the category in individual operations:
await cache.SetAsync("product:123", product, new CacheEntryOptions
{
Category = "products"
});Per-key options override category defaults. Category defaults override global defaults.
Access metrics via cache.Metrics.Snapshot:
var snapshot = cache.Metrics.Snapshot;
Console.WriteLine($"Hits: {snapshot.Hits}, Misses: {snapshot.Misses}, Size: {snapshot.Size}");| Field | Description |
|---|---|
Hits |
Cache hits. |
Misses |
Cache misses. |
StaleHits |
Stale values served during revalidation. |
Sets |
Set operations. |
Removals |
Explicit removals. |
Evictions |
Entries removed due to expiration. |
Size |
Current number of tracked entries. |