Introduction
ShopNest product catalog under flash sale load needs caching — IMemoryCache for single server, Redis for distributed cache across multiple App Service instances.
After this article you will
- Apply cache-aside pattern for product lists
- Configure Redis IDistributedCache
- Invalidate cache on product updates
- Use output caching (.NET 8) on API endpoints
- Prevent cache stampede with locks
Prerequisites
- Article 47 — Background Services
- ShopNest API, EF Core, and DI from prior modules
Concept deep-dive
public async Task<ProductDetailDto?> GetProductAsync(int id, CancellationToken ct)
{
var key = $"product:{id}";
if (_cache.TryGetValue(key, out ProductDetailDto? cached))
return cached;
var product = await _db.Products.AsNoTracking()
.ProjectTo<ProductDetailDto>(_mapper.ConfigurationProvider)
.FirstOrDefaultAsync(p => p.Id == id, ct);
if (product != null)
_cache.Set(key, product, TimeSpan.FromMinutes(10));
return product;
}
// Redis
builder.Services.AddStackExchangeRedisCache(options =>
options.Configuration = config["Redis:Connection"]);
// Output caching — .NET 8
[OutputCache(Duration = 60, VaryByQueryKeys = new[] { "page", "categoryId" })]
[HttpGet]
public async Task<IActionResult> List() => Ok(await _service.GetPageAsync());
Stampede: use SemaphoreSlim or FusionCache library so only one thread repopulates cold cache.
Hands-on — ShopNest High-Traffic Product Catalog
- Redis in Docker Compose for local ShopNest.
- Cache-aside on GET product; Remove on PUT/DELETE.
- OutputCache on product list API.
- Load test before/after — document latency improvement.
Common errors & best practices
- Caching personalized data with public key — user A sees user B data.
- No TTL — stale prices after admin update.
- IMemoryCache in multi-instance production — each server different cache.
Interview questions
Q: Cache-aside?
A: App checks cache, on miss loads DB and sets cache.
Q: Cache invalidation?
A: Delete/update cache keys when source data changes — hardest part of caching.
Q: Output vs response caching?
A: Output caching (.NET 8) caches full endpoint result at server.
Summary
- Redis shares cache across ShopNest web farm
- Cache-aside + invalidation keeps catalog fresh
- Output caching speeds read-heavy list endpoints
- Prevent stampede on hot keys during sales
Previous: Background Services
Next: Health Checks
FAQ
Redis vs SQL for cache?
Redis is in-memory, sub-ms — SQL poor fit for hot cache layer.
What to cache?
Read-heavy, relatively stable data — not unique per-user secrets.