Aggressive caching for a Mastodon reverse proxy: what to cache, what to never cache, and why content negotiation will eventually betray you
a day ago
- Mastodon serves different content (HTML, ActivityPub JSON, API JSON) for the same URL based on the Accept header, requiring careful cache key normalization.
- The cache key must include a normalized variant of the Accept header to prevent serving the wrong content type to clients.
- Key assumptions: AUTHORIZED_FETCH disabled, no signed URLs, federation uses HTTP Signatures (not Authorization header).
- Bypass cache logic is decomposed into small orthogonal maps for method, authorization, cookie, and URI patterns.
- Short TTLs (10–30 seconds) are used for dynamic public endpoints, while immutable assets have TTLs of days.
- proxy_cache_lock prevents thundering herds, and proxy_cache_use_stale enables stale-while-revalidate for static assets.
- The Vary header from upstream is ignored, and the proxy takes full responsibility for correct content negotiation.
- Logging includes cache status and variant bucket to verify behavior in production.
- Caveats include: short TTLs cost CPU, stale-while-revalidate can hide problems, AUTHORIZED_FETCH changes caching rules, and Set-Cookie responses must never be cached.
- The main goal is to reduce requests reaching Puma/Rails by absorbing repetitive public traffic at the proxy layer.