Skip to content
All writing ‹ Part 12 of 18 · A Cache Is a Chain, Not a Box
Engineering · 3 min read

TTL Is Set in Three Places

The TTL of one file is set in three places: bucket metadata, the LB cache, and the CDN rule. It can only go down on the way, and a blank in IaC means default.

One place does not decide the TTL of a file. Three layers each have a setting. The TTL passes from storage to the client and can only go down on the way.

I thought TTL was set only on the CDN. When I dug in, I found three places on the path that decide it.

① bucket object metadata Cache-Control not set→ default max-age=3600 ② LB cache setting client TTL cap 3600→ outgoing max-age is at most 3600 ③ Akamai rule default 30 days, but obeysthe max-age from the origin browser gets the seconds left on the Akamai copy
The TTL passes from the bucket to the browser through three settings, and each layer can only push it down.

The Setting at Each Layer

LayerSettingOur value
① BucketCache-Control metadata on the objectNot set at upload, so the bucket returns public, max-age=3600
② LB cachecache modeCache all static files
default TTL / client TTL cap / max TTL3600 / 3600 / 86400
stale-while-revalidate time86400 (Stale-While-Revalidate: Serve Old First, Refresh in the Background)
③ Akamaicaching behaviorObey Cache-Control and Expires, default 30 days
  • In the “cache all static files” mode, the client TTL cap is the upper limit of the max-age that the LB cache sends out.
  • So even if I set 30 days at upload, a file on the proxy route reaches Akamai with at most 3600 seconds.
  • “Can only go down” holds only if Akamai obeys the max-age it receives. If Akamai uses a fixed TTL, it sits closest to the client and can override the values behind it (Cache Freshness: Fresh, Stale, and 304).
  • The LB cache also rewrites this header: the bucket returns public, max-age=3600, and after the LB cache it becomes public,max-age=3600.

No Written Setting Does Not Mean No Setting

We manage config with IaC (Infrastructure as Code). The LB cache rules were not written there, so I thought it had no rules. But when the cache is on, it always has a full set of defaults. I asked the cloud platform directly and read the real values.

A blank in IaC does not mean “none”. It means “default”.

Sources: RFC 9111: HTTP Caching

Related: Cache Freshness: Fresh, Stale, and 304, Cache Headers: Who Sets, Who Reads, The Path of One Request, Stale-While-Revalidate: Serve Old First, Refresh in the Background, What I Learned: A Cache Is a Chain, Not a Box. Or go back to the series overview.

↑↓ navigate ↵ open esc close