DEV Community

Dev Nestio
Dev Nestio

Posted on • Originally published at devnestio.pages.dev

HTTP Cache-Control Builder: Toggle Directives, Detect Conflicts, Copy Code

Cache-Control is one of the most impactful HTTP headers for performance, but it is also one of the easiest to misconfigure. I built a visual builder that lets you toggle directives on and off, warns you about conflicting combinations, and generates code for Express, nginx, Apache, and CloudFront.

Tool

HTTP Cache-Control Builder
https://devnestio.pages.dev/cache-control-builder/

Features: 8 quick presets, 13 directives, conflict detection, and framework snippets.

no-store vs no-cache: The Key Distinction

This is the most common point of confusion:

Directive Meaning
no-store Never store this response anywhere
no-cache Store it, but revalidate with the server before using it

no-cache does NOT mean "don't cache". It means "always check if the cache is still valid". When combined with ETag or Last-Modified, the server can return 304 Not Modified and save bandwidth.

The 8 Presets

Static assets (hashed filenames)

Cache-Control: public, max-age=31536000, immutable
Enter fullscreen mode Exit fullscreen mode

When filenames include a content hash (app.a3f2c1.js), content never changes at that URL. immutable tells the browser to skip revalidation during max-age.

HTML pages

Cache-Control: public, max-age=0, must-revalidate
Enter fullscreen mode Exit fullscreen mode

HTML is often the entry point for SPAs or contains dynamic content. Cache it (to get 304s) but always revalidate.

Authenticated API responses

Cache-Control: private, no-cache
Enter fullscreen mode Exit fullscreen mode

private prevents CDNs from caching. no-cache forces revalidation on every request.

Never cache (sensitive data)

Cache-Control: no-store, private
Enter fullscreen mode Exit fullscreen mode

CDN-heavy setup (longer CDN TTL, shorter browser TTL)

Cache-Control: public, max-age=3600, s-maxage=86400
Enter fullscreen mode Exit fullscreen mode

s-maxage overrides max-age for shared caches (CDNs) only.

Stale-While-Revalidate

Cache-Control: public, max-age=60, stale-while-revalidate=86400
Enter fullscreen mode Exit fullscreen mode

Serve stale content for up to 86400s while revalidating in the background. Great for content that can tolerate being slightly out of date.

Conflicts the Tool Detects

  • public + private — mutually exclusive
  • no-store + no-cacheno-store is stronger, no-cache is redundant
  • no-store + max-ageno-store overrides max-age
  • immutable + no-cache — contradictory ("never changes" + "always revalidate")
  • must-revalidate + no-store — can't revalidate if nothing is stored

Express Implementation

// Static assets
app.use('/static', express.static('public', {
  maxAge: '1y',
  immutable: true,
}));

// HTML entry point
app.get('/', (req, res) => {
  res.setHeader('Cache-Control', 'public, max-age=0, must-revalidate');
  res.sendFile(path.join(__dirname, 'public/index.html'));
});

// Private API
app.use('/api/me', (req, res, next) => {
  res.setHeader('Cache-Control', 'private, no-cache');
  next();
});
Enter fullscreen mode Exit fullscreen mode

nginx

# Static assets
location /static/ {
    add_header Cache-Control "public, max-age=31536000, immutable" always;
}

# HTML
location / {
    add_header Cache-Control "public, max-age=0, must-revalidate" always;
}

# API
location /api/ {
    add_header Cache-Control "private, no-cache" always;
}
Enter fullscreen mode Exit fullscreen mode

https://devnestio.pages.dev/cache-control-builder/

Top comments (0)