Skip to main content

Static assets and CDN delivery

Serve CSS, JS and images efficiently, and know when a CDN is worth it.

Static assets are everything that is not generated per request: images, CSS, JavaScript, fonts, video segments. Serving them well is most of web performance.

The basics that always help

  1. Cache headers. Tell browsers how long to keep an asset:

text
Cache-Control: public, max-age=31536000, immutable

Use long lifetimes with fingerprinted filenames (app.a1b2c3.js) so a new deploy gets a new URL and never serves stale code.

  1. Compression. Brotli or gzip for text (CSS/JS/HTML/SVG) — typically 70%+ smaller.

  2. Modern image formats. WebP/AVIF over JPEG/PNG, served at the size actually displayed.

  3. Set explicit dimensions on images and video so the layout does not jump (hurts Core Web Vitals).

  4. Minify and bundle CSS/JS to cut request count and bytes.

Where to store them

  • Small sites — alongside the app on the web server. Fine, and simplest.

  • Growing sites — object storage for user uploads and large media, so the web server stays stateless and rebuildable — see Object storage basics.

When a CDN earns its keep

A CDN caches your assets at edge locations near your visitors:

  • Geographically spread audience — big latency win.

  • Media-heavy site — offloads the heavy traffic from your origin.

  • Traffic spikes or attacks — the edge absorbs load.

For a small, single-region site with a nearby audience, a CDN may add complexity for little gain. Match the tool to the audience.

Implementing a CDN

  1. Point the CDN at your origin.

  2. Set long cache TTLs for static assets, short (or none) for dynamic pages.

  3. Purge the cache on deploy where you are not using fingerprinted filenames.

  4. Add an origin cache-busting strategy so you never serve stale HTML.

  5. Watch for mixed content — a CDN over HTTPS must not pull assets over HTTP.

Measure it

Track TTFB, latency and bandwidth before and after. A CDN should reduce origin bandwidth and improve response times for remote users; if it does not, check the cache hit ratio (low ratio = misconfigured caching).

Related reading