---
title: "Static vs Dynamic Content: The Complete Edge Caching Guide"
description: "Learn what to cache at the edge, how to handle dynamic and personalized content, and how to verify cache correctness without leaking data."
canonical_url: https://optimi.com/en/guides/static-vs-dynamic-content
md_url: https://optimi.com/en/guides/static-vs-dynamic-content.md
last_updated: 2026-07-14
---

# Static vs Dynamic Content: The Complete Edge Caching Guide

The useful question is not whether a page is static or dynamic, but whether a particular response is safe and valuable to reuse.

"Static" and "dynamic" are useful development labels, but they are incomplete caching policies. A product page may be generated from a database and still be safe to cache briefly. A static-looking HTML document may contain a user-specific recommendation or cookie and must not be shared. Edge caching works when you classify the response, its inputs, freshness tolerance, and failure impact.

The goal is not to maximize the cache-hit ratio at any cost. The goal is to reuse safe responses, keep personalized data private, reduce origin work, and make freshness predictable.

## What static and dynamic really mean

Static content is usually identical for many users: hashed JavaScript, stylesheets, fonts, logos, public images, downloads, and versioned media. These objects are excellent candidates for long-lived caching because a URL change can represent a content change.

Dynamic content is produced or selected at request time: search results, inventory, recommendations, account pages, carts, checkout, and APIs. Dynamic does not automatically mean uncacheable. A public catalogue response can be reused briefly if its cache key captures the query. Conversely, an endpoint based on a cookie or authorization token is not safe to share just because the URL is stable.

> **Cache the representation, not the implementation**
>
> Ask who can receive this response, what request inputs change it, how long it may be reused, and what happens if the origin is unavailable.

## A practical classification model

Use four categories when designing edge rules:

1. **Immutable public assets.** Versioned files can have long shared and browser lifetimes. Keep old versions available while cached HTML still references them.
2. **Public, time-sensitive content.** News, category pages, and public product data can use a bounded shared TTL, validators, tags, or background revalidation.
3. **Public but request-specific content.** Search and filtered listings may be cacheable if the key includes the meaningful query, locale, currency, and other inputs. Normalize tracking parameters only when they do not change the answer.
4. **Private or personalized content.** Account, cart, checkout, payment, and user-specific API responses should generally use `private` or `no-store`, or bypass shared caching entirely.

The [HTTP caching standard](https://www.rfc-editor.org/rfc/rfc9111.html) defines shared and private caches, freshness, validation, cache keys, and restrictions around authorization. Use it as the baseline rather than a provider's default behavior.

**Classify each response before deciding its edge policy**

![Decision flow that asks whether a response contains private or personalized data, whether all public requests receive the same representation, whether versioned content is immutable, and whether a request-specific public representation has a reviewed cache key. The outcomes are bypass shared caching, long immutable caching, bounded public caching with validation, or public variant caching with explicit key inputs.](/diagrams/static-vs-dynamic-content/response-classification.svg)

*Server rendering does not make a response uncacheable, and a static-looking URL does not make it safe to share; reuse follows the representation's audience and inputs.*

## Step-by-step edge caching design

### 1. Start at the origin

Make the application emit an intentional policy. `Cache-Control: public` indicates that a response may be shared when other requirements are met. `max-age` controls general freshness, while `s-maxage` can set a different lifetime for shared caches. `private` prevents shared reuse, and `no-store` instructs caches not to store the response. `no-cache` means a stored response must be validated before reuse; it does not simply mean "do not cache."

Pair freshness with validators. An `ETag` lets a cache ask whether the representation changed without downloading it again. `Last-Modified` enables time-based validation. Send `Vary` when the representation changes based on a request header such as `Accept` or `Accept-Language`.

### 2. Define the cache key

At minimum, the key usually includes the method and target URI. Review every additional dimension:

- Query parameters that change filtering, sorting, currency, or pagination.
- Language and country selection.
- `Accept` values when format negotiation changes the body.
- Device or client hints, only if the output truly differs.
- Cookies and authorization, which are often a reason to bypass rather than expand the key.

An over-specific key creates many cold variants and pushes requests back to the origin. An under-specific key can serve the wrong content. Normalize only inputs that are demonstrably irrelevant, and test the result with two requests that should produce different answers.

### 3. Separate public HTML from private fragments

For a page with both public and personalized areas, cache the public shell and fetch private data separately, or compose the response using a mechanism designed for safe edge assembly. Do not cache the whole HTML document and assume a cookie will be ignored. A CDN may reuse the document for another user unless the policy or key prevents it.

For APIs, use endpoint-specific rules. A public product feed and a customer order endpoint may share a hostname but should not share a blanket cache policy. Never let a broad file-extension rule decide whether JSON is safe to reuse.

### 4. Choose freshness and stale behavior

Set TTLs from business tolerance, not from a generic number. A logo can stay fresh for a day or longer when versioned. A category page may tolerate minutes. Availability and price may require a much shorter window or a live request. Where acceptable, `stale-while-revalidate` can hide revalidation latency, and `stale-if-error` can preserve public content during an origin failure. The [RFC 5861 extensions](https://www.rfc-editor.org/rfc/rfc5861.html) describe these behaviors.

Never serve stale account, cart, payment, or authorization-sensitive data simply to improve availability. The cost of an old public headline is not the cost of an old price or private balance.

### 5. Plan updates and purges

Version what can be versioned. For stable URLs, attach content tags or surrogate keys so a product update can invalidate the product page, listing, and related fragments without clearing the entire cache. A URL purge is appropriate for a single object; a prefix or full purge should have a documented blast radius.

Read the [cache purging guide](/en/guides/cache-purging) for a release sequence that publishes before it invalidates. Optimi's [managed CDN guide](/en/performance/cdn) covers the edge delivery layer and cache-hit visibility.

## Verify correctness and speed

Build a test matrix before production:

- Anonymous visitor versus authenticated visitor.
- First request versus repeat request.
- Desktop versus mobile or client hints.
- Each supported language, country, currency, and format.
- Relevant query parameters with different expected results.
- Origin success, timeout, and error behavior.

Inspect `Cache-Control`, `Age`, `ETag`, `Vary`, `Set-Cookie`, authorization handling, and provider cache-status headers. A response with `Set-Cookie` deserves scrutiny, but its absence does not prove a response is public. Compare bodies or a version marker, not only `HIT` and `MISS`.

Measure origin request volume, cache-hit ratio, response age, TTFB, error rate, and Core Web Vitals by page type. PageSpeed Insights reports field experiences at the 75th percentile when enough data exists; use field data alongside controlled tests rather than substituting one for the other.

## Rollback and recovery

Keep a simple switch for every policy change: disable the new rule, restore the previous configuration, or route the affected path to the origin with caching bypassed. If the wrong public response was cached, purge its URL or content tag after the origin is corrected. If private data may have been shared, treat it as a security incident: stop reuse immediately, purge all affected variants, rotate or invalidate exposed sessions as appropriate, and review logs.

For a performance regression, avoid blindly shortening all TTLs. Identify whether the cause is key fragmentation, a bypass rule, a missing validator, an origin error, or a refill storm. Correct the failing rule and warm representative objects gradually.

## Common mistakes

- Calling all server-rendered pages dynamic and caching none of them.
- Caching all successful `GET` responses without reviewing cookies or authorization.
- Ignoring `Vary` after serving multiple image or language representations.
- Putting every query parameter into the key, or stripping parameters that change content.
- Using `no-cache` when the real requirement is `no-store`, or vice versa.
- Serving stale prices, stock, carts, or account data for availability.
- Measuring only one warm browser and calling that edge performance.

For image-specific decisions, read [image optimization for ecommerce](/en/guides/ecommerce-image-optimization) and Optimi's [Adaptive Image page](/en/performance/adaptive-image). Ecommerce teams can connect these rules to the [ecommerce solution](/en/solutions/ecommerce), and teams planning multiple delivery paths can read [the resilience guide](/en/guides/website-resilience).

> There are only two hard things in Computer Science: cache invalidation and naming things.

[Contact Optimi](/en/contact): Turn caching into a reliable policy — Talk to our team about separating public, dynamic, and personalized delivery at the edge.
