What to Cache at the Edge, What to Cache at Origin, and What to Stop Caching Entirely

Edge caching stores responses close to end users, usually in a CDN or regional proxy layer. Origin caching stores responses at your own infrastructure, typically in Redis, Varnish, or an application-level cache. The two layers solve different problems, and a lean team that treats them as interchangeable will eventually debug a stale object at 2 a.m. This article separates the layers, gives concrete rules for what belongs where, and names the cache entries that should be removed from your configuration this week.

For a team of two to fifteen engineers running cloud-native infrastructure, cache policy is not a performance garnish. It is a correctness and cost control. A bad edge rule can serve outdated content to thousands of users. A bad origin rule can hide a database failure until traffic spikes. A cache that stores the wrong object can turn a small incident into a long one. The goal is not to cache everything. The goal is to cache the right things at the right layer and to make the rules boring enough to survive an on-call rotation.

Why the Edge and Origin Are Different Systems

The edge is geographically distributed. It is good at absorbing read traffic, reducing latency, and shielding the origin from repetitive requests. The origin is centralized. It is good at enforcing consistency, applying business logic, and serving as the source of truth. When a response is cached at the edge, the origin may not see the request at all. When a response is cached at the origin, the application still receives the request but avoids a slower downstream operation such as a database query or a third-party API call.

This distinction matters because the two layers have different invalidation behavior. Edge caches are often controlled by CDN configuration, cache headers, and purge APIs. Origin caches are controlled by application code, TTLs, and key design. A lean team should be able to answer two questions for any cached object: Where does it live? and What happens when it is stale? If the answer is unclear, the cache rule is too clever.

What to Cache at the Edge

Edge caching works best for public, read-heavy, and relatively static content. The classic examples are product images, marketing pages, JavaScript bundles, CSS files, fonts, and public API responses that do not vary by user. These objects are requested frequently, change infrequently, and do not contain private data.

Static Assets and Versioned Files

Versioned assets are the safest edge cache candidates. A file named app-3f2a1b.js or hero-image-v2.webp can be cached for a year because a change produces a new URL. The old URL can remain cached without serving incorrect content. This is the simplest cache invalidation model available: no invalidation at all.

For a small team, the rule should be: if the asset is not versioned, do not give it a long edge TTL. A short TTL of five to fifteen minutes is acceptable while the team works toward versioned builds. The long-term fix is to make the build pipeline produce immutable URLs.

Public Read-Heavy API Responses

Some API responses are safe to cache at the edge. A public list of blog posts, a product catalog endpoint, or a configuration file that is the same for all anonymous users can be cached for seconds or minutes. The key is that the response must not depend on the requesting user, the request body, or a session token.

Edge caching for APIs is most useful when the origin is small and the read pattern is spiky. A CDN can absorb a traffic spike that would otherwise exhaust application workers. But the team must be able to purge or version the cache when the underlying data changes. If the application cannot issue a purge, the edge TTL should be short enough that staleness is acceptable.

What Not to Cache at the Edge

Do not cache authenticated responses at the edge unless the cache key includes a user identifier and the CDN is configured to isolate those objects. Even then, the risk of leaking one user’s data to another is real. Most lean teams should keep authenticated responses at the origin or use a very short private cache.

Do not cache write responses. POST, PUT, PATCH, and DELETE responses should not be stored at the edge. A cached redirect after a form submission can cause duplicate actions. A cached error response can make an outage look permanent.

Do not cache responses that depend on request headers you cannot normalize. If the response varies by Accept-Language, Accept-Encoding, or a custom header, the edge cache key must include those values. Otherwise, one user’s variant will be served to another.

What to Cache at the Origin

Origin caching is the layer your application controls directly. It is the right place for data that is expensive to compute, shared across users, or sensitive enough that it should not live in a third-party edge network. Common origin caches include Redis, Memcached, and in-process caches such as a dictionary or a library-level cache.

Database Query Results

A query that runs on every request and returns the same result for many users is a good origin cache candidate. Examples include feature flags, site settings, navigation menus, and reference data such as country lists or tax rates. The cache reduces database load and keeps the application responsive when the database is slow.

The tradeoff is staleness. If a feature flag is cached for five minutes, a rollout takes five minutes to reach every user. That is usually acceptable. If a price is cached for five minutes, a pricing error can persist for five minutes. The TTL should match the business tolerance for stale data, not the engineering desire for speed.

Expensive Computations

Some responses are not database-bound but CPU-bound. A report, a resized image, a search result, or a machine-generated summary can be cached at the origin after the first computation. The cache key should include all inputs that affect the output. If the computation depends on a user role, the key must include that role or the cache must be per-user.

Origin caches are also useful for third-party API responses. If your application calls a payment provider, a geocoding service, or a shipping calculator, caching the response can reduce cost and latency. But the cache must respect the third party’s terms and the freshness requirements of the data. A cached shipping quote that is two hours old may be wrong by the time the customer checks out.

Session and User-Specific Data

User-specific data can be cached at the origin, but the cache key must include the user identifier and the cache must be private. A common pattern is to cache a user profile or a set of permissions for a few minutes. This reduces database reads without exposing data to other users. The risk is that a permission change takes effect slowly. If a user is removed from a project, the cached permissions may allow access until the TTL expires.

For lean teams, the safer pattern is to cache user data for a very short time or to invalidate the cache on change. A five-minute TTL is often a reasonable default. A one-hour TTL for permissions is usually not.

What to Stop Caching Entirely

Some cache entries create more risk than they remove. The following categories are common sources of stale data, debugging confusion, and incident length. If your configuration includes them, remove or redesign them.

Error Responses

Caching error responses is a common mistake. A 500 error cached for ten minutes can make a transient failure look like a full outage. A 404 cached for an hour can hide a newly published page. The rule is simple: do not cache 5xx responses. Cache 404s only for truly static paths, and keep the TTL short.

If your CDN or application has a default rule that caches all responses, change it. The default should be to cache only successful responses with explicit cache headers. Everything else should pass through or be cached for seconds at most.

Personalized Content Under a Public URL

A URL that serves different content to different users should not be cached at the edge without a user-specific cache key. This includes pages that show a user’s name, account status, or recommendations. The failure mode is severe: one user sees another user’s data. If the page must be cached, use a private cache directive or move the personalization to a separate request.

Volatile Data with No Invalidation Path

If a value changes frequently and the application cannot purge or version the cache, do not cache it. This includes inventory counts, live prices, and real-time status. A cache that cannot be invalidated is a bug waiting for a customer to find it. The fix is either to build an invalidation path or to accept the database read.

For a small team, the invalidation path is often the harder part. A purge API, a message queue, or a versioned key scheme all require code and operations. If the team is not ready to build that, the cache should not exist.

A Decision Framework for Lean Teams

When a new cache rule is proposed, run it through four questions:

  1. Is the response public or private? Public responses can go to the edge. Private responses stay at the origin or use a private cache.
  2. How often does the underlying data change? If the change frequency is lower than the TTL, the cache is safe. If not, the cache will serve stale data.
  3. What is the cost of staleness? A stale blog post is fine. A stale price or permission is not. The TTL should reflect the cost.
  4. Can the cache be invalidated? If the team cannot purge or version the cache, the cache is a liability.

This framework is deliberately simple. It does not require a cache expert. It requires the team to be honest about what they can operate. A cache rule that passes the framework today may fail it next quarter when the data changes or the team shrinks. Review cache rules during incident postmortems and quarterly maintenance.

Cache Headers and TTLs That Work

The most common cache headers are Cache-Control, ETag, and Vary. A lean team should standardize on a small set of patterns rather than inventing a new header for every endpoint.

  • Immutable assets: Cache-Control: public, max-age=31536000, immutable
  • Public API responses: Cache-Control: public, max-age=60, s-maxage=300
  • Private user data: Cache-Control: private, max-age=300
  • No-store for sensitive operations: Cache-Control: no-store

The s-maxage directive controls shared caches such as CDNs. It allows the edge to cache for longer than the browser. This is useful when the edge can be purged but the browser cannot. The Vary header should be used sparingly. Each additional Vary value fragments the cache and reduces hit rates.

Monitoring Cache Behavior

A cache that is not monitored will eventually misbehave. The minimum monitoring for a lean team is three metrics: hit rate, stale object count, and purge latency. Hit rate tells you whether the cache is doing its job. Stale object count tells you whether invalidation is working. Purge latency tells you how long a change takes to reach users.

Most CDNs and cache systems expose these metrics. The team should look at them during incidents and during normal operations. A sudden drop in hit rate can indicate a key change or a configuration error. A rise in stale objects can indicate a broken invalidation path.

Cache monitoring should be part of the same dashboard as application errors and latency. If the cache is healthy but the application is slow, the problem is elsewhere. If the cache is unhealthy, the application will look slow even when it is not.

Incident Learning and Cache Policy

Cache-related incidents are usually caused by one of three things: a missing invalidation path, a cache key that does not include a critical input, or a default rule that caches too much. Each of these is a policy failure, not a one-off mistake. The fix is to change the policy, not to add a special case.

After a cache incident, write down what was cached, where it was cached, and why the stale object was served. Then update the decision framework or the standard header patterns. This is the same discipline as writing a recovery checklist before you need it. A recovery checklist that includes cache purge steps can shorten the next incident by minutes.

For a small team, the postmortem should produce a concrete change: a new header rule, a removed cache entry, or a new purge endpoint. If the postmortem produces only a discussion, the same incident will happen again.

Common Questions

Should I cache HTML pages at the edge?

Only if the HTML is public and does not vary by user. A marketing page or a public blog post can be cached at the edge. A dashboard or an account page should not be. If the HTML contains a CSRF token or a user-specific element, keep it at the origin or use a private cache.

What is a reasonable default TTL for API responses?

For public API responses, start with 60 seconds at the browser and 300 seconds at the edge. For private responses, start with 60 seconds or less. The TTL should be based on how often the data changes and how much staleness the business can tolerate. A shorter TTL is safer and easier to reason about.

How do I know if a cache is causing a bug?

If a user reports seeing old data, another user’s data, or a page that should not exist, suspect the cache. Check the cache headers, the cache key, and the invalidation path. Purge the object and see if the bug disappears. If it does, the cache is the cause. If it does not, the bug is in the application.

Should I cache database query results in Redis?

Yes, for queries that are expensive, shared across users, and tolerant of staleness. Use a cache key that includes all query parameters. Set a TTL that matches the data’s change frequency. Invalidate the key when the underlying data changes, or accept the staleness window.

Next Steps for Your Team

Start with an inventory. List every cache rule in your CDN, application, and infrastructure. For each rule, answer the four questions from the decision framework. Remove the rules that fail. Then standardize the remaining rules into a small set of header patterns and TTLs.

The result should be a cache policy that fits on one page. When a new endpoint is built, the team applies the policy instead of inventing a new rule. When an incident occurs, the team checks the policy first. This is the difference between a cache that helps and a cache that hides problems.

For teams that want to go further, the next step is to write a cache purge runbook. The runbook should list every cache layer, the purge command or API for each, and the order in which to purge them. This is a natural companion to the recovery checklist and belongs in the same operations manual.

FAQ

What is the difference between edge caching and origin caching?

Edge caching stores responses in a distributed network close to users, typically a CDN. Origin caching stores responses in your own infrastructure, such as Redis or an application-level cache. Edge caching reduces latency and shields the origin from traffic. Origin caching reduces database load and computation time.

What should never be cached at the edge?

Never cache authenticated responses, write responses, error responses, or content that varies by user without a proper cache key. These objects can leak data, cause duplicate actions, or serve stale errors. The safest edge cache candidates are public, versioned, and read-heavy assets.

How long should I cache public API responses?

A common starting point is 60 seconds at the browser and 300 seconds at the edge. The TTL should be based on how often the data changes and how much staleness the business can tolerate. If the data changes frequently or the cost of staleness is high, use a shorter TTL or no cache at all.

What is the most common cache mistake for small teams?

The most common mistake is caching without an invalidation path. A team adds a cache rule, sees a performance improvement, and then cannot update the cached object when the data changes. The result is stale data and a confusing incident. Every cache rule should have a purge or versioning mechanism before it is enabled.

Should I cache error responses to reduce load during an outage?

No. Caching error responses can make a transient failure look like a full outage and hide recovery. A 500 error cached for ten minutes will continue to be served after the origin has recovered. The default rule should be to cache only successful responses with explicit cache headers.

Team reviewing cache configuration on a whiteboard
Server rack with network cables in a data center
Engineer monitoring cache metrics on a laptop