ASP.NET Core › Caching

How would you cache the results of an expensive, paginated database query while correctly handling different page/filter parameter combinations?

Advanced

Answer

Include all parameters that affect the query's result set (page number, page size, sort order, filter values) as part of the cache key, since caching under a key that ignores a parameter would return the wrong page/filtered results to a subsequent request with different parameters -- Output Caching's VaryByQueryKeys handles this declaratively for HTTP-level caching, while application-level caching requires manually composing a sufficiently unique key string.
// Application-level: composite key including all relevant parameters
var cacheKey = $"products-page{page}-size{pageSize}-sort{sortBy}-category{category}";

// Output Caching: declarative equivalent
[HttpGet]
[OutputCache(VaryByQueryKeys = new[] { "page", "pageSize", "sortBy", "category" })]
public IActionResult GetProducts(int page, int pageSize, string sortBy, string category) { ... }
Real-world example A bug where users saw identical results regardless of their selected sort order was traced to a cache key that only included the page number, not the sortBy parameter, causing the first-cached sort order to be returned for every subsequent request.

Common follow-ups: What happens if you forget to include a parameter that affects the query in the cache key?;How does an overly granular cache key (too many parameter combinations) hurt cache hit rate?