The edge caching decision record: why the cache key model you chose determines your origin protection ceiling and your stale content surface

Published 2026-07-16 · WhyChose

Edge caching decisions are made when the team first needs to reduce origin server load, improve response time for frequently-requested resources, or absorb traffic spikes without scaling the origin horizontally. The AI session that configures edge caching is practically grounded and reaches a working state quickly: it selects a CDN provider or configures caching at the reverse proxy layer, sets TTLs on static assets — long TTLs for CSS, JavaScript, and image files that change infrequently — and shorter TTLs or no-cache directives on API responses and dynamically generated HTML pages, verifies that repeated requests to the same URL return cached responses with the expected X-Cache: HIT header, and confirms that origin server load drops measurably after the cache layer is in front of it. The session ships a caching configuration that works correctly in the test environment and demonstrably reduces origin traffic at the traffic volumes the team is testing against.

What the AI session does not produce is the caching layer's second half. The session answers "which URLs, which TTLs, and how do we confirm the cache is working?" and delivers a working cache configuration. It does not ask: what is the cache key model — which request dimensions beyond the URL determine a cache hit, and if the response varies based on the requester's authentication state, locale, or accepted content encoding, does the cache key include those dimensions or does the bypass policy exclude personalized requests from the cache entirely? What is the invalidation strategy — when origin content changes, how is the cached version removed before its TTL expires, and if invalidation is required faster than the TTL allows (a pricing error, a content moderation takedown, a security disclosure that requires updating all cached pages immediately), what is the invalidation mechanism and what is the known set of cached URLs that must be purged for a given content object change? What is the stale-while-revalidate contract — when a cached item's TTL expires and the origin is temporarily slow or unavailable, does the cache serve the stale version while refreshing in the background, and for how long, and is the stale-serving window documented so that operators know the maximum age a user can receive during a cache revalidation event? What is the origin stampede protection mechanism — when a high-traffic URL expires in cache simultaneously for thousands of concurrent requests, does the cache coalesce those requests into a single origin fetch or does each cache miss produce an independent origin request, and what is the amplification factor at the team's peak traffic rate and expected TTL configuration? What is the cache hierarchy model — if the CDN architecture includes edge PoPs that check a regional shield cache before reaching the origin, what is the TTL at each layer, and does a 5-minute edge TTL compounded with a 5-minute regional TTL produce a 10-minute maximum stale window rather than the 5 minutes the team assumed when setting the edge TTL? Each of these questions has an answer that is not derivable from "we set Cache-Control: max-age=300 on API responses" as the team frames the configuration. Each answer determines whether the caching layer is a reliable performance multiplier that protects the origin and serves consistent content, or becomes the mechanism by which authenticated users receive each other's personalized response panels, a pricing error remains visible to users for the full TTL window because no invalidation path exists, and a scheduled content release produces a synchronized origin stampede when the release-date TTL expires for a high-traffic URL. The answers exist in the AI sessions. They are the operational commitments behind the cache configuration. They are almost never written down.

Two ways edge caching decisions produce the wrong outcome in production

The URL-only cache key and the personalized content leak

A B2B SaaS platform builds its first CDN configuration in its second year of operation. Until this point, all responses are generated by the application server on every request — no intermediate caching between the user and the origin. As the user base grows, the team observes that dashboard pages with complex data aggregations are taking 800 to 1,200 milliseconds to generate, and the aggregate origin server load is high during peak usage hours. The performance optimization decision is made: add a CDN in front of the application server and cache dashboard pages with a 10-minute TTL to absorb repeated requests. The founding session configures the CDN: static assets (CSS, JS, fonts, images) get a 1-year Cache-Control max-age with immutable headers since the team deploys with content-hash filenames that change on every build; HTML pages for the main dashboard routes get a 10-minute Cache-Control max-age with a short stale-while-revalidate window; API endpoints used for background data refresh get a 2-minute max-age. The session tests the configuration by loading the dashboard as an anonymous user and as a logged-in user, verifying that both experience a cache hit on the second request to the same URL, and confirming that the origin server's CPU utilization drops by approximately 40% during the load test with the CDN in front of it. The CDN ships and the team observes the expected improvement in dashboard load times and a reduction in origin server load during peak hours.

Seven months after the CDN is deployed, a customer support ticket arrives: a customer at a small company with three seats reports that one of their users is seeing another user's dashboard data — the account name displayed in the top-right corner of the application is the name of a different user in the same account, the activity feed shows another user's recent actions, and the "Recently viewed" panel shows records the reporting user has never opened. The support team investigates and discovers that all three users in the account have the same dashboard URL — the platform uses URL routing of the form /dashboard with no user-specific path component; user-specific data is returned based on the session cookie attached to the request. The CDN cache key is the URL only. All three users are routed to the same CDN edge node, and the first user's dashboard response — generated from the origin with the first user's session cookie — was cached at the CDN edge under the /dashboard URL key. When the second and third users requested /dashboard within the 10-minute TTL window, the CDN returned the first user's cached response. The session cookie in the browser is not sent with the cached response — the CDN serves the cached HTML — but the session cookie is also not included in the cache key, so the CDN cannot distinguish between the three users' requests.

The incident is a data leak: one user's account name, activity feed, and recently viewed records were served to two other users. The engineering team immediately configures the CDN to bypass the cache for all requests that include a session cookie — a correct fix — but the bypass-on-cookie rule was not designed from the start because the session demonstrated that the cache was working (in a test environment with a single test user where no cross-user contamination was possible), and the cookie bypass rule appeared to be an optimization for the future rather than a security requirement for the present. The post-incident review identifies that the cache key model was not documented: there was no written record of which request dimensions the CDN used to determine a cache hit, the test scenario did not include multiple users with different session states requesting the same URL, and the assumption that "we'll add personalization exclusions when we need them" was never recorded as a deferred decision with a documented trigger condition. The founding session that configured the URL-only cache key did not address: does any response at any cached URL vary based on the requester's authentication state or identity, and if so, does the cache key include the session dimension or does the bypass policy exclude those requests from the cache? A question that determined whether the caching layer was a performance optimization or a data leak mechanism serving one user's personalized responses to another's browser.

The TTL-only invalidation model and the pricing error that couldn't be corrected

A marketplace platform launches with an edge caching configuration that caches product listing pages with a 1-hour TTL, category pages with a 2-hour TTL, and homepage content with a 4-hour TTL. The TTL values are chosen based on the expected content update frequency: product listings change infrequently (new stock, price updates happen once or twice per day), category pages change even less frequently (new categories are added monthly), and homepage content is curated editorially and updated on a weekly publishing schedule. For the first eight months of operation, the TTL model works well: cache hit rates are high, origin load is low, and content freshness is acceptable because the actual update frequency matches the assumed update frequency the TTL values were chosen to accommodate.

Eleven months after launch, the marketplace runs its first major promotional event — a 48-hour flash sale. One hour before the sale begins, the team updates prices for 340 products across 18 category pages. The price updates are made in the origin database and immediately visible to any request that bypasses the cache or arrives after a cache miss. But 340 product listings are currently cached across the CDN's edge nodes with up to 1 hour of remaining TTL, and the 18 category pages are cached with up to 2 hours of remaining TTL. When the sale begins and traffic spikes to 12× the normal rate, the majority of requests receive cached responses showing the pre-sale prices — not the discounted prices that the team had spent the prior week configuring and the marketing team had promoted in the launch email. The engineering team attempts manual URL purges. They know the 340 product listing URLs and submit purge requests for those; the purge API confirms invalidation within thirty seconds. The category pages, however, are more complex: each product appears on multiple category pages (the product's primary category, a "Featured this week" editorial category, and a "Flash sale" category the team added specifically for the event), and the team does not know which of the 60+ cached category page URLs need to be purged for each product. After two hours of manually constructing a list of URLs to purge and submitting batched purge requests, 12 of the 18 affected category pages have been successfully purged. The remaining six are eventually cleared by TTL expiry — but not before three hours of the sale's peak window have elapsed with incorrect prices visible to users navigating through category views.

The post-incident analysis identifies three missing decisions from the founding caching configuration. First, there was no documented relationship between content objects (product, category, homepage section) and the set of cached URL variants that depend on each content object — the team knew that product price changes should invalidate product listing pages but had not mapped the complete set of URLs that show product prices. Second, there was no invalidation mechanism beyond TTL expiry and manual URL purge: the platform had not implemented surrogate key (cache tag) headers in its origin responses, so grouped invalidation — purge all cached responses that depend on product:8923 atomically — was not available. Third, there was no emergency invalidation runbook: the decision about what to do when cached content must be updated faster than the TTL allows was made ad hoc during the incident rather than in advance, when the answer was "enumerate affected URLs manually and submit individual purge requests." The founding session that set 1-hour and 2-hour TTL values did not address: what is the maximum acceptable staleness for each content type during a time-sensitive content update, and is TTL expiry the only invalidation mechanism, or is there a faster-than-TTL path for corrections that cannot wait? A question that determined whether the caching layer was a reliable performance infrastructure that could be updated promptly when content changed, or became the mechanism by which a planned promotional event launched with three hours of incorrect pricing because the invalidation model required enumerating 60+ cached URLs by hand under production incident pressure.

Three structural properties that edge caching decisions determine

The cache key model and the content variation surface

The cache key model determines which request properties the caching layer uses to distinguish between requests that should receive the same cached response and requests that should receive different responses — either from a distinct cache entry or from the origin directly. The most common cache key is the request URL: two requests for the same URL receive the same cached response. A URL-only cache key is correct when the response is genuinely identical for all requesters — a static CSS file, a publicly available JSON dataset, an unauthenticated product listing where every anonymous visitor sees the same content. It is incorrect when the response varies on dimensions not captured in the URL: the requester's authentication state (logged in versus anonymous), the requester's account identifier or role (which determines which data is included in the response), the requester's locale (Accept-Language header, which determines which language and regional formatting the response uses), or the requester's accepted content type (Accept header, which determines whether the response is HTML, JSON, or another serialization format).

The HTTP Vary header is the standard mechanism for communicating to caching layers which request headers affect the cached response. A response with Vary: Accept-Language instructs intermediate caches and CDNs to include the Accept-Language header value in the cache key, so that a French-locale request and an English-locale request for the same URL are treated as distinct cache entries. A response with Vary: Cookie instructs caches to include the Cookie header in the cache key — but Vary: Cookie is almost never the correct approach for session-based personalization, because the Cookie header contains all cookies sent by the browser, and the complete cookie string is rarely the correct cache key dimension (it includes tracking cookies, analytics cookies, and feature flag cookies whose values change frequently and are irrelevant to the cached response variant). The standard pattern for session-based personalization is not Vary: Cookie but cache bypass: requests that carry a session cookie indicating an authenticated user are excluded from the cache entirely and forwarded to the origin, while requests without a session cookie (anonymous visitors) are cached normally. The bypass rule must be documented as a policy: "all requests with a non-empty session-cookie header are forwarded to the origin; only requests without a session cookie are eligible for caching." The bypass policy must account for the full set of authentication indicators — session cookies, Authorization headers, X-Auth-Token headers, or other identity signals — and exclude all of them from the cacheable request pool. A bypass rule that excludes requests with a session-cookie named __session but not requests with an Authorization: Bearer header will cache authenticated API responses under the URL-only key, reproducing the same personalized content leak with a different authentication mechanism.

The cache key model also determines the cache hit rate and the origin load protection ceiling. A cache key that is too broad — URL only, when responses actually vary on headers — serves incorrect responses to some requesters and may leak data. A cache key that is too narrow — URL plus the complete raw Cookie header — produces a near-zero cache hit rate because the exact cookie string varies per user per session, and every request produces a cache miss. The correct cache key is the minimal set of dimensions that the response actually varies on: URL plus locale for locale-specific responses, URL plus accepted content type for content-negotiated responses, URL-only for fully public responses, and bypass-the-cache-entirely for session-personalized responses. The CDN decision record is the upstream document for the edge caching configuration: the CDN provider selection, the edge PoP topology, and the traffic routing model determine which caching layer first processes each request, and the cache key model must be specified consistently across all CDN providers in a multi-CDN setup — a URL-only key at one provider and a URL-plus-Accept-Language key at another will produce different cached response variants for the same URL across different edge locations.

The invalidation strategy and the stale content surface

The invalidation strategy determines how cached content is removed or replaced before its TTL expires when the origin content changes. There are three distinct invalidation mechanisms, each with different operational characteristics: TTL expiry alone, URL-specific purge, and surrogate key (cache tag) invalidation.

TTL expiry is the default: cached content is automatically invalidated when its TTL elapses, and the next request after expiry triggers a fresh fetch from the origin. TTL expiry requires no active invalidation operation and no knowledge of which URLs are currently cached — it is self-healing by design, and its simplicity makes it the default choice in a founding caching session. Its operational constraint is that it guarantees invalidation only within the TTL window: content that changes at the origin will remain visible in stale form to cache consumers for up to TTL seconds after the change. For static content types with infrequent updates — published blog posts, product documentation, archived event pages — TTL expiry is often the correct invalidation model because the update cadence is slow enough that the TTL window is acceptable. For content types that require faster-than-TTL invalidation — prices, availability indicators, compliance text, security advisories, product content subject to moderation — TTL expiry alone is insufficient.

URL-specific purge allows the engineering team to send an explicit invalidation request to the CDN for one or more specific URLs, removing those entries from the cache immediately regardless of their remaining TTL. URL-specific purge is correct when the team knows precisely which URLs must be invalidated for a given content change, and when the set of affected URLs is small enough to enumerate manually or programmatically. Its operational constraint is that it requires accurate knowledge of the cached URL space: the complete set of URLs that depend on the changed content object. For a simple product detail page at /products/12345, the URL set is one entry. For a product price that appears on the product detail page, three category listing pages, two search result pages, a featured-products API endpoint, and a homepage widget, the URL set is seven to nine entries — and accurately enumerating them at the moment of a content change requires maintaining and querying a documented relationship between content objects and their cached URL representations. This mapping is almost never documented in a founding caching session because at founding scale the URL space is small and the team knows the content structure informally.

Surrogate key invalidation (cache tags) solves the URL-enumeration problem by inverting the relationship: instead of the team tracking which URLs depend on a content object, the origin server tags each cacheable response with the identifiers of the content objects it depends on. When a product with ID 12345 changes, the team sends a single surrogate key purge request for product:12345, and the CDN atomically invalidates every cached response tagged with that key — the product page, the category listings that include the product, the search result pages, the API endpoints, and the homepage widget — without the team needing to know the URL set. Surrogate key invalidation requires that the origin emits surrogate key headers (Surrogate-Key or Cache-Tag, depending on the CDN provider) on every cacheable response. An origin response for a category page that includes products 1234, 5678, and 9012 would emit Surrogate-Key: category:electronics product:1234 product:5678 product:9012 — causing the CDN to register that cached response as depending on all four keys. A price change to product:5678 then purges not just the product detail page for 5678 but the category:electronics listing (and every other listing that included product:5678). The operational cost of surrogate key invalidation is the instrumentation work at the origin: every response-generating code path must emit the correct surrogate key set. The decision record must specify the surrogate key naming convention, the entity types that have surrogate keys, the code path responsible for emitting keys on each response type, and the purge API integration that triggers invalidation when content objects change. The database read replica decision record is the complementary document: caching and read replication are the two primary mechanisms for reducing read load on the primary database; the cache miss rate determines the volume of read traffic that flows through to the database layer, and the invalidation strategy determines how promptly the cached layer reflects updates that were written to the primary and replicated to the read replicas.

The bypass policy and the origin protection ceiling

The bypass policy defines the complete set of request conditions under which a request is forwarded directly to the origin without consulting the cache. The bypass policy serves two purposes: protecting the integrity of personalized or sensitive responses (not serving one user's cached data to another), and protecting the origin from traffic volumes that the cache is not configured to absorb. The bypass policy must enumerate every bypass condition explicitly: authenticated requests (requests with a session cookie, an Authorization header, or another authentication signal); write operations (POST, PUT, PATCH, DELETE — requests that modify state should never be served from cache and should never populate the cache with their response); administrative endpoints (routes that access administrative interfaces, internal tooling, or low-traffic paths where caching provides no benefit and where stale administrative data can cause operational confusion); and debugging overheads (requests with a Cache-Control: no-cache header from the browser should reach the origin to support developers who need to verify fresh origin behavior without clearing CDN caches).

The stale-while-revalidate directive is the bypass policy's backstop for origin availability: it specifies that after a cached item's TTL expires, the cache may continue serving the stale version for an additional window while it sends a background revalidation request to the origin. A Cache-Control: max-age=300, stale-while-revalidate=60 header instructs the cache to serve the response for 300 seconds, then to continue serving the stale response for up to 60 additional seconds while fetching a fresh version from the origin in the background. If the origin is unavailable during the revalidation window, the cache continues serving the stale response for the stale-while-revalidate duration and then either returns a cache miss error or falls back to a stale-if-error window if configured. The stale-while-revalidate window has two operational implications: it reduces the origin request rate for high-traffic URLs (instead of every concurrent request at the moment of TTL expiry hitting the origin simultaneously, a single background revalidation request handles the refresh for all concurrent requests served stale during the window), and it guarantees that users may see content up to max-age + stale-while-revalidate seconds old, which must be acceptable for the content type it is applied to. A product listing page with max-age=300, stale-while-revalidate=60 may show content up to 6 minutes old during a background revalidation event — a tolerance that must be documented and accepted by the team before the directive is deployed, not discovered during a post-incident review when an outdated price was visible for 6 minutes instead of the expected 5.

Origin stampede protection is the cache bypass policy's interaction with TTL expiry at high traffic rates. When a cached item's TTL expires and a large number of concurrent requests arrive before the cache is repopulated, each request produces a cache miss and is forwarded to the origin — a request burst proportional to the site's per-URL request rate multiplied by the origin response time. For a URL receiving 2,000 requests per second with a 400-millisecond origin response time, a cache miss at peak traffic can produce up to 800 simultaneous origin requests before the cache is repopulated. Request coalescing (also called request collapsing or cache lock) prevents this: the first request to arrive at a cache miss takes the lock and is forwarded to the origin; subsequent requests for the same URL that arrive while the lock is held wait for the origin response and are served the response when it arrives, without themselves being forwarded to the origin. The decision record must specify whether request coalescing is enabled, whether the CDN or reverse proxy layer supports it natively, and how it interacts with stale-while-revalidate (a common implementation serves stale content immediately to all concurrent requests while a single coalesced revalidation request runs in the background, eliminating both the stampede and the user-visible wait that coalescing without stale content would impose). The real-time architecture decision record is the companion document for the bypass policy's interaction with live-data surfaces: pages or API endpoints that serve real-time or near-real-time data must either bypass the cache entirely or use a very short TTL combined with stale-while-revalidate, and the decision about which real-time surfaces bypass the cache must be recorded explicitly rather than discovered when a user reports that a real-time dashboard shows 5-minute-old data because it was included in the caching configuration without an explicit bypass rule.

Three AI session types that embed edge caching decisions without documenting them

The performance optimization session is where edge caching first appears in a system — typically when the team has identified high origin server load, slow page generation times, or excessive database read traffic as the primary performance constraint. The session adds a CDN or configures caching at the reverse proxy layer, sets TTL values based on the team's intuition about how frequently each content type changes, and verifies that cache hit rates are high and origin load is reduced. The cache key model that emerges from this session is almost always URL-only, because the test scenario involves a single developer or a handful of test accounts requesting the same URLs and observing cache hits — a scenario that does not expose the content variation surface. The session documents "we added CDN caching with the following TTL values" without documenting "the cache key is URL-only, and the following content types are excluded from the cache because their responses vary by requester identity." The exclusions are absent not because the team decided authenticated responses should be cached — they generally assume they shouldn't be — but because the question was never explicitly asked and the test scenario never produced a collision between two different users' cached responses at the same URL. The open-source extractor surfaces these founding performance optimization sessions from AI chat history, recovering the CDN configuration rationale, the TTL value choices, and the response-type classification that determined which URLs were included in the cache without the team having to reconstruct the original reasoning from the final CDN configuration and the history of subsequent performance incidents.

The traffic spike mitigation session is where TTL values become aggressive and invalidation gaps become consequential. The session is typically triggered by an anticipated traffic event — a product launch, a promotional campaign, a mention in a high-traffic publication — where the team needs the caching layer to absorb traffic that could be 10× to 100× the normal sustained rate. The session extends TTLs to maximize cache hit rates and reduce origin exposure: a 5-minute TTL becomes a 1-hour TTL, a 10-minute TTL becomes a 4-hour TTL. The session does not simultaneously design an invalidation strategy for the longer TTL windows, because at the moment of the traffic spike event the content is expected to be correct — the team just published it — and the question of how to correct cached content urgently does not arise until a content error is discovered during or after the event. The longer TTL values persist in the CDN configuration after the traffic event, because no one changes them back (the original motivation for the shorter TTLs was performance, and the longer TTLs demonstrate better performance), and the next content update that requires sub-TTL visibility discovers that the only correction mechanism is manual URL purge and the team does not know the complete URL set. The multi-cloud strategy decision record is the upstream context for the traffic spike mitigation session in organizations using multiple CDN providers or a multi-region CDN configuration: a TTL change made in one CDN's control plane does not propagate to other providers, and a surrogate key purge submitted to one CDN's API does not invalidate cached responses at other CDN providers, so the invalidation strategy must be designed for the complete CDN topology rather than for a single provider's configuration panel.

The infrastructure modernization session is where a single-CDN, single-origin configuration is replaced with a multi-tier caching hierarchy — CDN edge PoPs that check a regional shield cache before reaching the origin, or a reverse-proxy cache at the application layer that sits between the CDN and the database-backed application server. The session is focused on reducing origin traffic further and improving global performance by adding cache layers closer to the users. What the session does not address is the TTL interaction between cache layers: a 5-minute TTL configured at the CDN edge layer, combined with a 5-minute TTL configured independently at the regional shield layer, produces a maximum stale content window of up to 10 minutes — not 5 minutes as the team assumed when they set the edge TTL and assumed the regional layer would be transparent. A content update that reaches the origin at time T is reflected in the regional cache at time T+5m (when the regional layer's TTL expires and a fresh copy is fetched from the origin), and reflected in the edge cache at time T+10m (when the edge layer's TTL expires and a fresh copy is fetched from the regional layer, which is now showing the updated content). The TTL compounding effect must be documented explicitly for each cache layer in the hierarchy, along with the per-layer invalidation mechanism (surrogate key purge must be submitted to each CDN provider or cache layer independently; a purge at the edge layer that does not also purge the regional layer leaves the regional layer with the stale copy, which will repopulate the edge cache with stale content when the edge layer's TTL next expires after the purge). The secrets management decision record is the relevant companion for the infrastructure modernization session's operational credentials: CDN API keys for cache purge operations, surrogate key purge API credentials, and CDN configuration management tokens are infrastructure secrets that require rotation schedules and revocation procedures — they are high-value targets because a compromised CDN API key can be used to poison the cache by selectively purging high-traffic URLs and forcing cache misses that expose origin load, or to retrieve the current cache key configuration revealing which authentication dimensions the cache key does and does not include.

The five sections of an edge caching decision record

The first section documents the cache key model. The cache key must be defined per URL pattern or content type: "for URLs matching /products/*, the cache key is the URL path; for URLs matching /dashboard/*, caching is bypassed entirely for all requests with a session cookie header; for API endpoints under /api/v1/*, the cache key is the URL path plus the Accept-Language header value extracted from the request." The Vary header policy must be documented separately from the bypass policy: Vary headers communicate the cache key to intermediate caches and browser caches, not just the CDN, and an inconsistent Vary header (Vary: Cookie set on a page the team intends to bypass the cache for) can produce unexpected caching behavior at intermediate caches even when the CDN bypass rule is correctly configured. The personalization surface must be enumerated: every response type that includes user-specific data must either be excluded from the cache via an explicit bypass rule, or must have a cache key that includes the user identity dimension in a form that produces correct per-user cache isolation. A bypass rule that is documented but not enforced — "all authenticated requests bypass the cache" as a policy statement without an enforced CDN rule that checks for the session cookie and routes to origin — provides no protection. The decision record must specify the enforcement mechanism, not just the policy intent: the CDN rule name or condition expression that implements each bypass condition, and the test procedure for verifying that the bypass rule is applied correctly to authenticated requests. The new CTO onboarding problem in a system with an undocumented cache key model is the authentication dimension audit: an incoming technical leader finds a CDN configuration with URL-only cache keys, a bypass rule for session cookies that was added after an incident but does not cover Authorization header-based authentication (added in a subsequent session for the mobile API), and no documentation of which response types vary on which dimensions — requiring a comprehensive audit of every cached URL against the access control model to identify any remaining personalization leak vectors.

The second section documents the TTL model. TTL values must be documented per content type with the rationale for each value — not as arbitrary configuration numbers but as decisions that encode a stale tolerance assumption: "product listing pages use a 5-minute TTL; the acceptable stale window is 5 minutes for price and availability updates (confirmed with the product and operations teams before deployment); this assumes that price updates are not time-critical at minute-level granularity and that the content moderation team has at least 5 minutes to act on a reported content issue before the correct version propagates to the cache." The TTL values must be cross-referenced with the invalidation strategy: a 1-hour TTL is only acceptable if the team has an invalidation mechanism that can correct content in under 1 hour when required, or if the content type is genuinely acceptable to serve in stale form for up to 1 hour under any circumstances. A TTL value without an associated invalidation path for faster-than-TTL correction is an operational commitment that content errors in that type will persist for up to the TTL duration and there is no faster correction mechanism. The stale-while-revalidate window must be documented as an addendum to the TTL: "Cache-Control: max-age=300, stale-while-revalidate=60; the maximum observable content age during a background revalidation event is 360 seconds; this is acceptable for product listing content (confirmed), not acceptable for promotional pricing content during active sale events (promotional pricing uses a 60-second TTL with no stale-while-revalidate, and a surrogate key invalidation trigger on price field updates)." The TTL model must be reviewed and updated when the content update cadence changes — a blog post that was published weekly (making a 24-hour TTL acceptable) that begins to be updated multiple times per day (making a 24-hour TTL incorrect) requires a TTL change that may not be noticed without an explicit review process linked to the content publishing model.

The third section documents the invalidation strategy. The invalidation mechanism must be specified per content type: TTL-only for content where sub-TTL invalidation is never required; URL-specific purge for content where the affected URL set is small and deterministic for any given content change; surrogate key invalidation for content where a single content object change affects multiple cached URLs and the full URL set is not practical to enumerate at purge time. For any content type using URL purge or surrogate key invalidation, the content-object-to-cached-URL mapping must be documented: "a price change to a product (identified by product_id) invalidates the following URL patterns: /products/{product_id}, /api/v1/products/{product_id}, and any category listing URL that currently includes the product in its result set." For surrogate key invalidation, the naming convention must be specified — "surrogate keys use the format {entity_type}:{entity_id}, e.g. product:12345, category:electronics" — along with the origin code paths responsible for emitting surrogate key headers on each response type and the purge API call that triggers invalidation when a content object is updated. The emergency invalidation runbook must be documented as a separate operational procedure: "when a critical content error is discovered and requires immediate cache invalidation across all content types and URL patterns, the procedure is: (1) trigger a full surrogate key purge for the affected entity using the management API endpoint; (2) if surrogate keys are insufficient (e.g. global configuration change), submit a full-site purge request via the CDN control panel — note that full-site purge on CDN X takes approximately 30 seconds to propagate globally; (3) verify the purge by requesting the affected URL with a Cache-Control: no-cache header and confirming the response reflects the updated origin content." The emergency procedure must include the CDN control panel access path and the contact list for the infrastructure team members with purge API credentials, because an emergency cache invalidation at midnight requires that the on-call engineer can execute the purge without having to discover the access path under pressure.

The fourth section documents the cache hierarchy model. If the caching architecture includes multiple layers — CDN edge PoPs, a regional shield cache, an application-layer reverse proxy cache, or an in-process object cache — each layer's TTL, cache key model, and invalidation mechanism must be documented, along with the compounding TTL effect across layers. The decision record must include an end-to-end staleness analysis: for a content update made at time T to the origin database, what is the maximum time at which a user at each CDN edge location will receive the updated content, given the TTLs and invalidation propagation times at each cache layer? A 5-minute edge TTL and a 5-minute regional shield TTL produce a maximum staleness of 10 minutes at the edge without invalidation — or near-zero with surrogate key invalidation propagated to both layers simultaneously. The invalidation scope for multi-tier caches must be explicit: a surrogate key purge submitted to the CDN's edge layer does not automatically propagate to the regional shield layer if the shield is a separate caching system with an independent API; the purge must be submitted to each layer's API independently, and the propagation order must account for the fact that purging the edge before the shield will cause the edge to re-fetch from the shield and receive the still-stale shield copy, repopulating the edge cache with stale content and wasting the purge. The correct invalidation order in a two-layer hierarchy is shield-first, then edge — purge the regional cache so that when the edge's stale copy expires or is purged and it fetches from the shield, it receives the current origin content, not a shield-cached stale copy. This ordering dependency is a non-obvious operational detail that must be in the decision record rather than reconstructed by the on-call engineer during a time-sensitive content incident.

The fifth section documents the observability model. The caching layer's observability must provide four views that together characterize whether the cache is providing the intended protection and serving correct content: the cache hit rate by content type (the fraction of requests served from cache versus forwarded to the origin, broken down by URL pattern or content type, so the team can identify when a configuration change or a bypass rule addition has reduced the cache hit rate for a specific content class below the level needed for origin protection); the origin request rate as the primary health signal (the absolute rate of requests reaching the origin servers, which should be proportional to cache miss rate and inverse to cache effectiveness — a sudden increase in origin request rate indicates either a cache invalidation event, a cache bypass rule misconfiguration, a TTL storm where a large fraction of cached items expire simultaneously, or a traffic pattern change that reduces cache hit rate); the P95 time-to-first-byte from cache versus from origin (the latency improvement the cache provides, which quantifies the performance value of the caching layer and identifies content types where cache hits are not providing the expected latency improvement due to cache key design issues or bypass rules that are too broad); and the surrogate key distribution for pollution detection (the number of distinct cached URLs tagged with each surrogate key — a surrogate key that tags thousands of cached URLs may indicate an overly broad key that will cause unnecessary large-scale invalidation events when any of the tagged content objects changes, while a surrogate key that tags zero cached URLs may indicate that the origin code path is not emitting the key correctly). The decisions never written down in an edge caching deployment are the cache key model (which dimensions determine a cache hit and which are excluded), the invalidation strategy (TTL-only versus URL purge versus surrogate key, and the emergency runbook), and the TTL staleness tolerance (the acceptable stale window that each TTL value encodes, cross-referenced with the content types where sub-TTL invalidation may be required) — three properties that together determine whether the caching layer is an origin protection infrastructure that serves correct content promptly when it changes, or becomes the mechanism by which personalized responses are served to the wrong user, content errors persist for the full TTL window because no faster-than-TTL correction path exists, and origin stampedes occur at the boundaries of a TTL storm because the cache key, invalidation, and bypass policies were configured in the founding optimization session without documenting the content variation surface, the invalidation requirements, or the acceptable staleness tolerance for each content type the cache serves.

The performance optimization session that first added a CDN with a URL-only cache key and 1-hour TTL values, the traffic spike mitigation session that extended those TTLs to maximize cache hit rates before a promotional event without simultaneously designing an invalidation path, and the infrastructure modernization session that added a regional shield cache without documenting the compounding TTL effect or the layer-ordered invalidation requirement each produced edge caching decisions whose long-term operational cost — seven months of personalized content leak because the session cookie was not part of the cache key and the test scenario never exposed two users requesting the same URL within a single TTL window; three hours of incorrect promotional pricing because the invalidation model was TTL-only and the URL set for the affected products across category and search result caches was not enumerable under incident pressure; a 10-minute maximum stale window that the team thought was 5 minutes because the regional shield layer's independent TTL was not included in the staleness analysis — exceeds what a cache key model document, a surrogate key invalidation design, and a TTL staleness tolerance analysis would have cost at the time the founding decisions were made. The decisions are in the AI sessions: the CDN configuration that "sets max-age=3600 for product pages," the bypass rule that "adds session cookie detection later when we add personalization," the TTL extension that "improves cache hit rate for the launch" with no paired invalidation path. WhyChose's open-source extractor surfaces these founding caching sessions as structured decision records before the next personalized response is served to the wrong user's browser, the next time-sensitive content correction is delayed by the full TTL window, or the next cache hierarchy addition compounds the stale window beyond what the content update cadence tolerates. The decisions never written down in an edge caching deployment are the cache key model, the invalidation strategy, and the TTL staleness tolerance — the three operational commitments that determine whether the caching layer is a reliable performance infrastructure that protects the origin and serves correct content promptly, or becomes the mechanism by which the founding optimization session's implicit assumptions about content variation, update cadence, and user identity produce data leaks, content errors, and origin stampedes that are disproportionate to the simplicity of the Cache-Control header that started it all.

Further reading