How does ASP.NET Core serve static files, and how do you cache them?

ASP.NET Core Performance Basic 1–2 Yrs2–3 Yrs Conceptual 1 min read

Quick Answer

UseStaticFiles() serves files from wwwroot. Place it early in the pipeline (before routing/auth) so assets skip unnecessary processing. Set long cache headers on fingerprinted assets and use ETag/Last-Modified for the rest. .NET 9's MapStaticAssets adds build-time fingerprinting and compression automatically.

UseStaticFiles serves anything in wwwroot, and I put it near the top of the pipeline, before routing and auth, so a request for a CSS file doesn't run through authorization. For caching, the assets that have a content hash in their filename get Cache-Control: max-age=1year, immutable, because a new build changes the URL. Everything else relies on ETags. In production those files usually come from a CDN and the app's job is just to emit the right headers. .NET 9 added MapStaticAssets which does the fingerprinting and compression for you at build time.

  • Custom headers: UseStaticFiles(new StaticFileOptions { OnPrepareResponse = ctx => ctx.Context.Response.Headers.CacheControl = "public,max-age=31536000,immutable" }).
  • Only put max-age=1year, immutable on files whose URL changes when the content changes (a content hash in the filename).
  • Serve from a CDN in production; the app just needs correct cache headers.
  • Static files middleware doesn't require routing — keep it above UseRouting.