C# Academy · Lesson

Cache Policies and Invalidation

Control cache lifetime and tags.

Lesson 4 of 413 steps

Cache Policies and Invalidation is a free C# Academy lesson on CoddyKit. This is lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, and your progress syncs across the web and the CoddyKit app. The C# Academy course includes 4 lessons in total.

Named Policies

Rather than repeating cache settings on every endpoint, define reusable named policies once and reference them by name.

builder.Services.AddOutputCache(options =>
{
    options.AddPolicy("Short", policy =>
        policy.Expire(TimeSpan.FromSeconds(10)));
    options.AddPolicy("Long", policy =>
        policy.Expire(TimeSpan.FromMinutes(10)));
});

Applying a Named Policy

Reference the policy by its name when caching an endpoint.

app.MapGet("/catalog", GetCatalog)
   .CacheOutput("Long");

Cache Tags

Tags group related cached entries so you can invalidate them together. Tag an endpoint with Tag in its policy.

app.MapGet("/products", GetProducts)
   .CacheOutput(policy => policy
        .Expire(TimeSpan.FromMinutes(5))
        .Tag("products"));

IOutputCacheStore

Invalidation goes through IOutputCacheStore. Inject it and call EvictByTagAsync to purge every entry carrying a tag.

app.MapPost("/products", async (
    Product p, AppDb db, IOutputCacheStore cache, CancellationToken ct) =>
{
    db.Products.Add(p);
    await db.SaveChangesAsync(ct);
    await cache.EvictByTagAsync("products", ct);
    return Results.Created($"/products/{p.Id}", p);
});

Why Invalidate on Writes

A cached list becomes stale the moment underlying data changes. Evicting the relevant tag on every create, update or delete keeps reads fresh without waiting for expiry.

// After any mutation:
await cache.EvictByTagAsync("products", ct);

Tagging by Resource

Tag at a finer grain to evict just one item's cached responses, not the whole collection.

app.MapGet("/products/{id}", GetProduct)
   .CacheOutput(policy => policy.Tag("products"));
// Evict the single item's detail + the list together
await cache.EvictByTagAsync("products", ct);

Vary-By in a Policy

Combine expiration, tags and vary-by rules in one named policy for a complete caching contract.

options.AddPolicy("ProductList", policy => policy
    .Expire(TimeSpan.FromMinutes(5))
    .Tag("products")
    .SetVaryByQuery("page", "size"));

Custom Vary-By Value

VaryByValue lets you key the cache on arbitrary request data, such as a tenant id resolved from the request.

policy.VaryByValue(context =>
    new KeyValuePair<string, string>(
        "tenant",
        context.Request.Headers["X-Tenant"].ToString()));

Eviction vs Expiration

Two ways entries leave the cache:

  • Expiration: time-based, automatic via Expire.
  • Eviction: explicit, via EvictByTagAsync when data changes.

Use both: short expiry as a safety net, eviction for correctness.

// belt-and-suspenders: Expire(5min) + EvictByTag on write

Locking and Stampede Protection

Output caching coalesces concurrent misses by default: when many requests hit an uncached endpoint at once, only one runs the handler while the others wait. You can opt out with SetLocking(false).

policy.SetLocking(false); // allow concurrent regeneration

Distributed Output Cache

By default the store is in-memory and per-instance. For multiple servers, back it with a distributed store (e.g. Redis) so all instances share and invalidate the same cache.

// Register a distributed IOutputCacheStore implementation
// (e.g. a Redis-backed package) so EvictByTag works cluster-wide

Quick Check

Test your understanding of invalidation.

Recap

You learned cache policies and invalidation:

  • Define reusable named policies and apply them by name.
  • Tags group entries; IOutputCacheStore.EvictByTagAsync purges them on writes.
  • Combine expiration (automatic) with eviction (explicit).
  • Use a distributed store for multi-server deployments.

That completes the rate limiting and caching course.

Free to start

Learn C# with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
93
Lessons
346

Frequently Asked Questions

Is the “Cache Policies and Invalidation” lesson free?

Yes — the full text of “Cache Policies and Invalidation” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO. The C# Academy course includes 4 lessons in total.

What will I learn in “Cache Policies and Invalidation”?

Control cache lifetime and tags. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

How long does the “Cache Policies and Invalidation” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Rate Limiting Algorithms
  2. Configuring Rate Limiting Middleware
  3. Output Caching Basics
  4. Cache Policies and Invalidation
← Back to C# Academy