Recipe: Caching¶
Goal¶
Add query caching with clear key conventions and safe invalidation.
Prereqs¶
- Base Clean Architecture template running.
- Decide on cache store (memory for development or
IDistributedCachein production).
Steps¶
- Add the caching package.
dotnet add src/Application/Application.csproj package CleanArchitecture.Extensions.Caching
dotnet add src/Infrastructure/Infrastructure.csproj package CleanArchitecture.Extensions.Caching
- Register caching services and configure TTLs.
builder.Services.AddCleanArchitectureCaching(
options => { options.DefaultNamespace = "MyApp"; },
behaviorOptions =>
{
behaviorOptions.DefaultTtl = TimeSpan.FromMinutes(5);
behaviorOptions.CacheNullValues = false;
});
- Add the query caching pipeline behavior.
builder.Services.AddMediatR(cfg =>
{
cfg.RegisterServicesFromAssemblyContaining<Program>();
cfg.AddCleanArchitectureCachingPipeline();
});
- Opt in queries to caching.
using CleanArchitecture.Extensions.Caching;
using CleanArchitecture.Extensions.Caching.Abstractions;
[CacheableQuery]
public record GetOrdersQuery : IRequest<OrdersVm>;
// or
public record GetUserQuery(int Id) : IRequest<UserDto>, ICacheableQuery;
- Add invalidation for write operations (commands or domain events).
Verify¶
- First call hits the data source; the second call hits cache.
- Different request parameters produce different cache keys.
Pitfalls¶
- Cache stampede: keep locking enabled and set jitter.
- Tenant-aware caching: install
CleanArchitecture.Extensions.Multitenancy.Cachingand callAddCleanArchitectureMultitenancyCachingwhen multitenancy is enabled. - Caching error responses: use
ResponseCachePredicateto skip them.