Output Caching

Wolverine.HTTP supports ASP.NET Core’s Output Caching middleware for server-side response caching. This is different from the client-side Response Caching that uses Cache-Control headers.

Response Caching vs. Output Caching

FeatureResponse Caching ([ResponseCache])Output Caching ([OutputCache])
Where cachedClient-side (browser)Server-side (in-memory)
MechanismSets Cache-Control headersStores responses in server memory
Cache invalidationBased on headers/expirationProgrammatic via tags or expiration
Use caseReduce bandwidth, leverage browser cacheReduce server processing, protect downstream services

For client-side response caching with [ResponseCache], see Caching.

Setup

First, register the output caching services and configure your caching policies:

builder.Services.AddOutputCache(options =>
{
    options.AddPolicy("short", builder => builder.Expire(TimeSpan.FromSeconds(5)));
});
 
builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("fixed", opt =>
    {
        opt.PermitLimit = 1;
        opt.Window = TimeSpan.FromSeconds(10);
        opt.QueueLimit = 0;
    });
    options.RejectionStatusCode = 429;
});

snippet source | anchor

Then add the output caching middleware to your pipeline. It should be placed after routing and authorization, but before MapWolverineEndpoints():

app.UseOutputCache();
 
app.UseRateLimiter();

snippet source | anchor

Per-Endpoint Usage

Apply the [OutputCache] attribute to any Wolverine.HTTP endpoint to enable output caching. This works exactly as it does in standard ASP.NET Core — no special Wolverine infrastructure is needed.

Using a Named Policy

[WolverineGet("/api/cached")]
[OutputCache(PolicyName = "short")]
public static string GetCached()
{
    return $"Cached at {DateTime.UtcNow:O} - {Interlocked.Increment(ref _counter)}";
}

snippet source | anchor

Using the Default (Base) Policy

[WolverineGet("/api/cached-default")]
[OutputCache]
public static string GetCachedDefault()
{
    return $"Default cached at {DateTime.UtcNow:O} - {Interlocked.Increment(ref _counter)}";
}

snippet source | anchor

Configuring Policies

Output cache policies are configured through AddOutputCache() in your service registration. Common options include:

Expiration

builder.Services.AddOutputCache(options =>
{
    // Base policy applied to all [OutputCache] endpoints without a named policy
    options.AddBasePolicy(builder => builder.Expire(TimeSpan.FromSeconds(30)));
 
    // Named policy with a shorter expiration
    options.AddPolicy("short", builder => builder.Expire(TimeSpan.FromSeconds(5)));
});

VaryByQuery and VaryByHeader

builder.Services.AddOutputCache(options =>
{
    options.AddPolicy("vary-by-query", builder =>
        builder.SetVaryByQuery("page", "pageSize"));
 
    options.AddPolicy("vary-by-header", builder =>
        builder.SetVaryByHeader("Accept-Language"));
});

Tag-Based Cache Invalidation

You can tag cached responses and then evict them programmatically:

builder.Services.AddOutputCache(options =>
{
    options.AddPolicy("tagged", builder =>
        builder.Tag("products").Expire(TimeSpan.FromMinutes(10)));
});

Then invalidate by tag when data changes:

public static async Task Handle(ProductUpdated message, IOutputCacheStore cacheStore)
{
    await cacheStore.EvictByTagAsync("products", default);
}

Important Notes

  • Output caching is a standard ASP.NET Core feature. Wolverine.HTTP endpoints are standard ASP.NET Core endpoints, so the [OutputCache] attribute works with no additional Wolverine-specific setup.
  • The UseOutputCache() middleware must be added to the pipeline for the attribute to take effect.
  • Output caching only applies to GET and HEAD requests by default.
  • Authenticated requests (those with an Authorization header) are not cached by default.

For the full set of configuration options, see Microsoft’s Output Caching documentation.



url: /guide/messaging/partitioning.md