Skip to content

Expires Headers

DodaTech 2 min read

title: "Expires Headers — Absolute Expiration for HTTP Caching" description: "The Expires header specifies an absolute expiration date for HTTP cached responses, providing backward compatibility with HTTP/1.0 caching systems." date: 2026-06-28 lastmod: 2026-06-28 weight: 14 tags: [apis, caching] }

The Expires header sets an absolute expiration timestamp in HTTP-date format, telling caches when a stored response becomes stale and must be revalidated.

What You'll Learn

  • Expires header format and usage
  • Expires vs Cache-Control max-age
  • When to use Expires in modern APIs

Why It Matters

While Cache-Control is preferred, Expires provides backward compatibility with HTTP/1.0 caches. Some CDNs and proxies still rely on Expires headers.

Code Examples

# Setting Expires header
from datetime import datetime, timedelta

@app.route('/api/reports/daily')
def daily_report():
    # Expires at midnight
    tomorrow = datetime.utcnow().replace(hour=0, minute=0, second=0) + timedelta(days=1)
    expires = tomorrow.strftime('%a, %d %b %Y %H:%M:%S GMT')

    response = jsonify(generate_report())
    response.headers['Expires'] = expires
    response.headers['Cache-Control'] = 'public, max-age=3600'
    return response

# Express.js Expires
app.get('/api/weather/forecast', (req, res) => {
  const nextUpdate = new Date();
  nextUpdate.setHours(24, 0, 0, 0);  // Expire at next midnight

  res.set({
    'Expires': nextUpdate.toUTCString(),
    'Cache-Control': 'public, max-age=3600'
  });
  res.json(forecast);
});
# Example Expires header
HTTP/1.1 200 OK
Content-Type: application/json
Expires: Mon, 29 Jun 2026 00:00:00 GMT
Cache-Control: public, max-age=3600

{"report": "data"}

Common Mistakes

1. Using Expires Without Cache-Control

Cache-Control overrides Expires. Set both for broader compatibility.

2. Wrong Date Format

Expires requires RFC 1123 format: Day, DD Mon YYYY HH:MM:SS GMT.

3. Setting Expires in the Past

Past expiration causes immediate cache invalidation.

4. Hard-Coded Expires Dates

Always compute expiration dynamically, not as a fixed string.

5. Relying Only on Expires

Expires is HTTP/1.0. Cache-Control max-age is more precise and flexible.

Practice Questions

  1. What HTTP-date format does Expires use?
  2. Does Cache-Control or Expires take precedence?
  3. Why set both Expires and Cache-Control?
  4. What happens when Expires is in the past?
  5. How do you compute Expires dynamically?

Answers:

  1. RFC 1123: Day, DD Mon YYYY HH:MM:SS GMT.
  2. Cache-Control max-age takes precedence over Expires.
  3. For backward compatibility with HTTP/1.0 caches.
  4. The response is immediately considered stale; no caching occurs.
  5. Add a duration to the current UTC time and format it.

Challenge: Audit your API responses. Add Expires headers to any responses that currently only use Cache-Control.

FAQ

Is Expires still relevant in HTTP/2?

: Yes. HTTP/2 doesn't change caching semantics. Expires still works.

What timezone should Expires use?

: Always GMT/UTC. Never use local time.

Can Expires be used with private responses?

: Yes. Expires applies regardless of public/private.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro