Performance and caching
Cache layers: from the browser to Redis
The same data can be cached in five places. Which one when, and how is it invalidated?
Understand the concept
There are many caching opportunities along a request’s path. The browser cache keeps static files and permitted responses on the user’s device. A CDN or proxy cache keeps responses that are identical for everyone at the edge. The Next.js data cache stores server-side fetch results with lifetimes and tags. On the API side an in-memory cache (IMemoryCache) works on one server, while a distributed cache such as Redis is shared by all servers. Finally the database has its own buffer pool.
The most common pattern is cache-aside: check the cache, on a miss fetch from the source and write to the cache. Key design is critical: everything that changes the response, such as language, filters and page, must be in the key; otherwise a Turkish request gets English data. In this project the Redis key includes language, filters and a ‘cache generation’.
The hard part is not caching but invalidating. A lifetime (TTL) is simple but stale for a while. Event-based invalidation (deleting the key or bumping the generation when a record changes) is fresh but every write path must do it. When the cache is unreachable the app must not fail; it falls back to the database.
A cache in the right layer cuts database load and response time many times over.
Forgetting to put a response-affecting parameter (language, user, page) in the cache key.
A letter’s journey through the city
Think of a request as a letter and the server as a city. Pick a scenario, press play and watch which gates the letter passes and where it gets stopped.
Someone else opens the same post. The tunnel is already open, so it leaves quickly.
One topic. Three levels of depth.
var key = $"post:{locale}:{slug}";
var json = await cache.GetStringAsync(key, ct);
if (json is null)
{
var post = await LoadFromDatabase(slug, locale, ct);
await cache.SetStringAsync(key, Serialize(post),
new() { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(2) }, ct);
return post;
}
return Deserialize(json);Cache-aside: cache first, otherwise database and write back.
This page connects to no real server or database. Code samples are illustrative for .NET 8, Next.js and SQL Server; timings are example values in the simulation, not measurements. Try samples only in your own development environment; never share real connection strings, tokens or passwords.
Try it yourself first.
You fixed a post title in the admin panel but the blog list shows the old title for 2 more minutes. How do you make it update immediately, and in which layers?
Show the solution and explanation
1) API: kayıt sonrası Redis nesil numarasını artır (liste anahtarları geçersiz).
2) Next.js: revalidateTag("public-posts") ile veri önbelleğini temizle.
3) CDN’de HTML önbellekleniyorsa ilgili yolu purge et.Each cache layer is invalidated separately. Clearing only one does not stop another from serving stale data.