Cache static files with expires and Cache-Control in Tengine

2026-09-30

Your pages load slowly even though the server is fast — the bottleneck is usually the browser downloading the same CSS and JS on every visit. The fix is static caching: tell the browser to keep those files for weeks. Tengine makes this a location block with two directives.

The standard static cache block

location ~* \.(css|js|png|jpg|jpeg|gif|svg|ico|webp|woff2?)$ {
    expires 30d;
    add_header Cache-Control "public, max-age=2592000";
    access_log off;
}

What this does:

The hashed-filename upgrade

Long caches have one risk: after a deploy, users keep old JS. If your build pipeline appends a content hash to filenames (app.a3f9c2.js), the filename changes on every deploy, so you can cache aggressively and never worry:

location ~* \.(css|js)$ {
    expires 1y;
    add_header Cache-Control "public, max-age=31536000, immutable";
    access_log off;
}

The immutable hint tells browsers not to even revalidate hashed assets.

What not to cache

Verify

curl -I https://yourdomain.com/css/style.css

Look for cache-control: public, max-age=2592000 and an expires header ~30 days out.

Summary

One location block caches all static assets for a month, cutting repeat-load time dramatically. Combined with Brotli and HTTP/2, your static site stops being a round-trip problem entirely.

Related articles