0Pricing
C# Academy · Lesson

Cache Policies and Invalidation

Control cache lifetime and tags.

Cache Policies and Invalidation is a free C# Academy lesson on CoddyKit — 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, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

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.

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, and the C# Academy course includes 4 lessons in total. 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.

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; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

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