How to add Cache-Control header to static resource in Spring Boot?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Adding a Cache-Control header to static resources is one of the simplest ways to make a Spring Boot application feel faster. The main decision is not whether to add caching, but how aggressive the cache should be for files such as JavaScript, CSS, fonts, and images that may change over time.
Why Static Resource Caching Matters
Browsers request static files repeatedly unless the response headers tell them otherwise. If the server marks those files as cacheable, the browser can reuse them instead of downloading them on every page load.
A typical policy for versioned static assets is:
- '
publicso shared caches may store the file.' - '
max-ageset to a long duration.' - Fingerprinted filenames, such as
app.9f1c2d.js, so a content change results in a new URL.
If filenames are not versioned, use shorter cache lifetimes to avoid serving stale files after a deployment.
Configure Cache Headers in Java
A version-agnostic Spring approach is to configure a resource handler with CacheControl:
With this configuration, files under src/main/resources/static that are served through /static/** receive a Cache-Control header with a long max age.
This approach is explicit and easy to review because the caching policy lives in application code.
Match the Policy to the Asset Strategy
Long-lived caching is safe only when the URL changes whenever the content changes. If you serve /static/app.js and replace the file during deployment, browsers may keep the old file until the cache entry expires.
That is why many production setups combine long max-age values with content hashing in filenames. Without that, you may prefer a shorter setting such as a few minutes or hours.
A more conservative example is:
That still reduces repeated downloads while lowering the risk of stale assets.
Spring Boot Property-Based Configuration
Depending on the Spring Boot version, some static resource cache settings can also be expressed through configuration properties. The exact property names have changed across Spring Boot releases, so Java configuration is often the safest answer when you want a stable pattern that works across versions with minimal ambiguity.
If you do use properties, verify them against the Spring Boot version running in your application rather than copying a snippet blindly from an older example.
Validate the Header
After configuring the handler, confirm the response header with a simple HTTP request:
You should see a response header similar to:
If the header is missing, check whether the request path actually matches the configured resource handler pattern.
When Not to Cache Aggressively
Do not apply long-lived cache headers to user-specific or frequently changing data just because it is served over HTTP. Static resources and dynamic responses are different categories.
For example, generated HTML or API responses often need very different caching rules. Cache static assets aggressively only when they are genuinely safe to reuse.
Common Pitfalls
A common mistake is using a very long max-age for non-versioned filenames. That often leads to browsers serving old CSS or JavaScript after a release.
Another issue is configuring the wrong path pattern. If the handler is registered for /static/** but the app serves assets from a different URL path, the header will never be applied.
People also assume Spring Boot properties are identical across versions. Some examples online use older property names, so confirm them before relying on them.
Finally, do not forget to test with a real HTTP request. It is easy to add configuration and assume the header is present without verifying the actual response.
Summary
- Add
Cache-Controlheaders to static resources to reduce repeated downloads. - '
WebMvcConfigurerwithCacheControlis a clear, version-stable Spring approach.' - Use long cache lifetimes only when asset URLs change with content changes.
- Validate the response with
curl -Ior browser developer tools. - Keep dynamic responses and static asset caching policies separate.
Related reading
- how to add cache control in AWS S3?
- How to add fault tolerance support to an existing MPI based system such that the system continues even after a machine goes down?
- How to Aggregate Asynchronous Messagges from a Queue into a Final Result at Scale?
- How to analyze logs in a distributed system?
- How to add context.xml file to embedded tomcat server
- How to add custom method to Spring Data JPA
- How to automatically scale up and scale down of micro services instances built using Spring Boot and Spring cloud?
- How to avoid merging high cardinality sub-select aggregations on distributed tables

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.