TTL Optimization: Balancing Freshness and Performance
Time-to-Live (TTL) is the fundamental parameter that controls how long cached content remains fresh before it must be revalidated or replaced. Every caching decision in a CDN ultimately reduces to a TTL value: too short and your origin absorbs unnecessary traffic; too long and users see stale content. Optimizing TTL values across different content types is one of the highest-impact performance improvements you can make, directly affecting cache hit ratios, origin load, and user experience.
What Is TTL and How Does It Work in CDN?
TTL stands for Time-to-Live and represents the duration in seconds that a cached object is considered fresh. When a CDN edge server receives a response from the origin, it stores the response along with its TTL. Subsequent requests for the same resource are served directly from the edge cache until the TTL expires, at which point the edge must revalidate with the origin or fetch a new copy.
TTL values flow from two sources: origin response headers and CDN configuration overrides. The origin sets TTL through Cache-Control headers (max-age, s-maxage) and the Expires header. The CDN can override these values through provider-specific rules, commonly called edge TTL or CDN TTL settings. When both exist, the CDN override typically takes precedence for the edge cache, while the original headers flow through to the browser.
What Are the Recommended TTL Values for Each Content Type?
Optimal TTL values depend on how frequently content changes, how critical freshness is, and how much origin load you need to absorb. The following table provides battle-tested recommendations for common content types:
| Metric | Edge Processing | Origin Processing | Improvement |
|---|---|---|---|
| Latency (p50) | 8–15 ms | 120–300 ms | 15–20x faster |
| Cache Hit Ratio | 85–95% | N/A | Reduces origin load |
| TLS Handshake | 1–5 ms (nearby PoP) | 50–150 ms | 10–30x faster |
| Bandwidth Cost | $0.01–0.04/GB | $0.05–0.12/GB | 3–5x cheaper |
| Availability | 99.99% (multi-PoP) | 99.9% (single DC) | 10x fewer outages |
| Content type | Edge TTL (s-maxage) | Browser TTL (max-age) | Rationale |
|---|---|---|---|
| Content-hashed JS/CSS | 365 days (31536000s) | 365 days (31536000s) | Filename changes on update; safe to cache indefinitely |
| Non-hashed JS/CSS | 24 hours (86400s) | 1 hour (3600s) | May change on deploy; shorter browser TTL for faster updates |
| Images (stable) | 30 days (2592000s) | 7 days (604800s) | Rarely change; high bandwidth savings |
| User-uploaded images | 7 days (604800s) | 1 day (86400s) | May be replaced; moderate TTL with purge capability |
| Fonts | 365 days (31536000s) | 365 days (31536000s) | Essentially never change; cache aggressively |
| HTML pages | 5-10 minutes (300-600s) | 0 (always revalidate) | Content changes frequently; browser always checks |
| Public API (read-only) | 1-5 minutes (60-300s) | 0-60 seconds | Data freshness important; short but meaningful |
| Private API | 0 (bypass) | 0 (no-cache or no-store) | User-specific; never cache at edge |
| Video/audio | 30 days (2592000s) | 7 days (604800s) | Large files; high origin cost per miss |
| RSS/XML feeds | 15 minutes (900s) | 5 minutes (300s) | Updated periodically; moderate freshness need |
These values are starting points. Adjust them based on your specific update frequency, traffic volume, and origin capacity.
How Do Browser TTL and Edge TTL Differ?
The separation between browser TTL and edge TTL is one of the most powerful tools in CDN caching. Understanding the distinction is critical for effective caching strategy design.
Browser TTL (max-age)
The max-age directive in Cache-Control controls how long the browser's local cache considers a response fresh. During this period, the browser serves the response from its own cache without contacting the CDN or origin at all. This eliminates network latency entirely but creates a blind spot: you cannot force a browser cache update from the server side.
Edge TTL (s-maxage)
The s-maxage directive controls how long CDN edge servers cache the response. Edges sit between the browser and origin, so an edge cache hit still requires a network round-trip from the browser to the edge, but it eliminates the longer round-trip to the origin.
The Split TTL Pattern
The most effective pattern sets different values for each layer:
Cache-Control: max-age=0, s-maxage=300, stale-while-revalidate=60
# Browser: always revalidate (0 seconds fresh)
# CDN edge: fresh for 5 minutes
# After 5 minutes: serve stale for 60s while refreshing in background
This pattern gives you CDN offloading (origin sees only one request per 5 minutes per edge per URL) while ensuring browsers always check for updates. The stale-while-revalidate window provides a seamless transition when the edge TTL expires. For deep coverage of the SWR directive, see stale-while-revalidate in CDN.
How Does the TTL Waterfall Work?
In a multi-tier CDN cache hierarchy, TTL values cascade through layers. Understanding this waterfall is essential for predicting actual cache behavior:
- Origin responds with
Cache-Control: s-maxage=300and a fresh copy of the content. - Origin shield (L3) caches the response. Its 300-second countdown starts.
- Regional cache (L2) fetches from the shield. The response includes an
Age: 10header indicating 10 seconds have already elapsed. The L2 cache starts with 290 seconds remaining. - Edge cache (L1) fetches from L2. The response arrives with
Age: 45. The edge starts with 255 seconds remaining. - Browser receives the response with
Age: 60. Usingmax-age=0, the browser immediately marks it for revalidation on the next visit.
The Age header accumulates across layers. If you set a 5-minute TTL at the origin, an edge server may have as little as 3-4 minutes of fresh cache time remaining after the response travels through intermediate tiers. Account for this when setting TTL values, especially at lower tiers.
What Are Effective TTL Override Strategies?
Most CDN providers allow you to override origin TTL values at the edge. This is useful when you cannot modify origin headers or need different caching policies than what the application sets.
CDN Edge Rules
Define TTL overrides based on path patterns, content type, or response status:
# Cloudflare Page Rule equivalent:
# URL pattern: *.example.com/static/*
# Edge Cache TTL: 1 month
# Browser Cache TTL: Respect existing headers
# Nginx proxy_cache configuration:
proxy_cache_valid 200 302 30d; # Cache success responses for 30 days
proxy_cache_valid 404 1m; # Cache 404s for 1 minute
proxy_cache_valid any 5m; # Default: 5 minutes
Override Precedence
When multiple TTL sources conflict, CDNs follow a priority hierarchy. The exact order varies by provider, but a typical precedence is:
- CDN edge rule (highest priority)
s-maxagein Cache-Control headermax-agein Cache-Control headerExpiresheader- CDN default TTL (lowest priority)
Document your TTL override strategy carefully. Silent overrides at the CDN layer can create confusing behavior when developers expect origin headers to control caching. Align your CDN overrides with your cache key design for predictable behavior.
How Do You Monitor and Optimize TTL Values?
Setting TTL values is not a one-time decision. Traffic patterns change, content update frequencies shift, and origin capacity evolves. Continuous monitoring reveals optimization opportunities.
Key Metrics to Track
- Cache hit ratio — The percentage of requests served from cache. Target 90% or higher for static content. Low hit ratios often indicate TTLs that are too short. See cache hit ratio optimization for improvement techniques.
- Age header distribution — Analyze the
Ageheader values in responses to understand how long objects typically live in cache before being requested. If most objects are served with Age values near zero, your TTLs may be shorter than necessary. - Origin request rate — Track requests reaching the origin over time. Increasing origin traffic despite growing user traffic suggests TTLs that are too short or cache key fragmentation.
- Stale-serve ratio — How often stale content is served via stale-while-revalidate. A high stale-serve ratio may indicate TTLs that are too short for your traffic volume.
Cache Age Distribution Analysis
Examine the distribution of Age header values across your content:
# Distribution analysis example:
# Age 0-60s: 45% of responses (recently cached or revalidated)
# Age 60-300s: 35% of responses (mid-life cache entries)
# Age 300-600s: 15% of responses (approaching expiry)
# Age 600s+: 5% of responses (stale-while-revalidate window)
If most responses are served with very low Age values, your content is being evicted or expiring before most users request it. Consider increasing TTL to improve the distribution spread and reduce origin load.
Can You A/B Test TTL Values?
TTL A/B testing is an advanced technique that helps find optimal values without risking the entire traffic base. The approach varies based on your CDN capabilities:
Edge-Side TTL Splitting
Use edge functions or CDN rules to set different TTL values for a percentage of requests. Compare origin load, cache hit ratios, and page load times between groups.
Path-Based Testing
Apply different TTLs to specific URL patterns that receive similar traffic. Compare performance metrics across the patterns to identify optimal values.
Gradual Ramp-Up
Increase TTLs incrementally rather than making large jumps. Move from 5 minutes to 15 minutes, monitor for a week, then move to 30 minutes if metrics improve. This catches issues early without exposing all users to potential staleness problems.
What Are Common TTL Mistakes to Avoid?
TTL configuration errors are among the most common CDN performance issues. Avoid these pitfalls:
- Setting TTL=0 for everything — This effectively disables caching. Every request hits the origin, defeating the purpose of the CDN. Even a 30-second TTL provides significant origin offloading under high traffic.
- Using the same TTL for all content — Static assets and dynamic HTML have fundamentally different update frequencies. A one-size-fits-all TTL either wastes cache potential on static assets or serves stale dynamic content.
- Ignoring browser TTL — Setting long
max-agevalues means users see cached content even after you purge the CDN. Uses-maxagefor edge caching and keepmax-ageshort for content that changes. - Not accounting for the Age header waterfall — A 5-minute TTL at the origin may result in only 3 minutes of effective cache time at the edge after traversing intermediate tiers.
- Forgetting negative caching — If you do not set TTLs for error responses, CDNs may cache 404s or 503s with default TTLs, causing persistent errors even after the origin recovers.
- Long TTLs without invalidation strategy — If you set a 30-day TTL, you need a reliable way to purge content when it changes. Without a purge mechanism, you are locked into stale content for the full TTL duration.
TTL optimization is an ongoing process, not a one-time configuration. Start with the recommended values in the table above, monitor your CDN performance metrics, and refine based on real traffic data. The goal is finding the longest TTL that still delivers acceptable content freshness for each content type, maximizing cache efficiency while maintaining the user experience your audience expects.