Skip to main content
CDN

Revalidation and purging

Refresh or invalidate CDN and Runtime Cache content before its TTL expires.

Cached content normally remains available until its configured lifetime expires. Easel also provides mechanisms to refresh or invalidate cached content before that happens.

Use revalidation when content should be regenerated while preserving normal cache behavior. Use purging when an existing cached entry should no longer be served.

Choose an approach

GoalRecommended approach
Refresh content after a fixed intervalSet s-maxage or framework revalidation
Accept a sync refresh after TTLSet s-maxage without stale-while-revalidate; the next request after expiry waits for a fresh response
Serve stale while refreshing in the backgroundSet s-maxage with an explicit stale-while-revalidate window
Invalidate related content across many URLsUse cache tags
Refresh a specific framework routeUse the framework’s revalidation API
Clear cached content for a deployment or projectUse project cache controls or ISR / deployment cache clear in the dashboard
Invalidate application valuesUse Runtime Cache tags or keys

Expiration, revalidation, and purging

These mechanisms solve different problems.

Expiration

Expiration happens automatically when a cached entry reaches the end of its configured lifetime.

CDN-Cache-Control: public, s-maxage=300

This response remains fresh for five minutes. After that, Easel must refresh it before it can be served as a fresh response again.

Revalidation

Revalidation refreshes stale content by running the route or contacting the origin again.

The resulting response can replace the previous cached entry.

Revalidation may happen:

  • after the configured TTL expires (the next matching request waits for a fresh response)
  • through a supported framework API
  • after a matching cache tag is invalidated

Purging

Purging invalidates cached content immediately instead of waiting for its TTL to expire.

Depending on the operation, a purge can target:

  • a cache tag
  • a deployment
  • a project environment
  • a supported framework path

After a purge, the next matching request normally produces a cache miss and regenerates or retrieves the response.

Time-based revalidation

Set a shared-cache lifetime with s-maxage:

CDN-Cache-Control: public, s-maxage=300

After five minutes, the entry is no longer fresh.

The next matching request waits while Easel obtains an updated response.

Use this approach when content changes predictably and a fixed refresh interval is sufficient.

Stale-while-revalidate

Set an explicit stale-while-revalidate window when you want Easel to serve the expired entry while refreshing it in the background:

CDN-Cache-Control: public, s-maxage=60, stale-while-revalidate=300

With this policy:

  • the response is fresh for 60 seconds (X-Easel-Cache: HIT)
  • for the next 300 seconds, Easel may serve the stale body (X-Easel-Cache: STALE) while refreshing in the background
  • after that window, the next request waits for a sync refetch

Omit the directive when you want a sync refresh after the fresh TTL. Easel does not invent a default stale window when the directive is absent. Frameworks such as Next.js may emit stale-while-revalidate for you.

Cache tags

Cache tags associate related cached content with a shared identifier.

A single tag can represent content used by:

  • multiple URLs
  • CDN response entries
  • Runtime Cache values
  • framework-generated pages
  • framework data-cache entries

For example, a product update may affect:

  • /products
  • /products/widget
  • /api/products/widget
  • a cached product query
  • a server-rendered category page

Tagging each related entry with product:widget allows them to be invalidated together.

Tag a response

Add one or more tags to a cacheable HTTP response:

Cache-Tag: products product:widget category:tools
CDN-Cache-Control: public, s-maxage=3600

Tags are separated by spaces.

Easel also recognizes compatible tag headers emitted by supported frameworks and adapters, including:

x-next-cache-tags: products,product:widget

and:

Surrogate-Key: products product:widget

When multiple supported tag headers are present, Easel associates their normalized tag values with the cached response.

Tag naming

Use stable, predictable tag names.

Good examples:

products
product:widget
category:tools
organization:acme
article:1248

Avoid tags that include:

  • timestamps
  • request IDs
  • session IDs
  • random values
  • unbounded user input

High-cardinality tags reduce their usefulness and can make invalidation harder to reason about.

A common convention is:

resource-type:identifier

For example:

product:123
customer:acct_42
collection:featured

Use broader tags alongside specific tags when updates can affect both one item and a collection.

Cache-Tag: products product:123

Purge by tag

Purging a tag invalidates every supported cache entry associated with that tag.

Conceptually:

Purge: product:123

Invalidates:
- /products/123
- /api/products/123
- category pages containing product 123
- tagged Runtime Cache values
- supported framework cache entries

Purging a tag does not require knowing every affected URL.

This makes tags suitable for content-management systems, product catalogs, dashboards, and other applications where one update can affect several views.

URL-level purge

URL-level PURGE is not a public product API.

To invalidate cached content, use:

  • cache tags
  • framework revalidation APIs such as revalidatePath or revalidateTag
  • ISR or deployment cache clear controls in the dashboard

Do not depend on purging a single URL as a customer-facing capability.

Framework revalidation

Supported frameworks can expose native revalidation APIs. Easel maps these operations onto the relevant platform cache layers.

Next.js

Revalidate a path

Use revalidatePath to refresh a route:

"use server";

import { revalidatePath } from "next/cache";

export async function updateProduct() {
  await saveProduct();

  revalidatePath("/products");
}

This invalidates the supported cached output associated with the path.

Revalidate a tag

Attach a tag to cached data:

const product = await fetch("https://api.example.com/products/123", {
  next: {
    tags: ["product:123"],
  },
});

Invalidate it after an update:

"use server";

import { revalidateTag } from "next/cache";

export async function updateProduct() {
  await saveProduct();

  revalidateTag("product:123");
}

Supported Next.js route, data, and response-cache entries can participate in the same tag invalidation flow.

See Next.js for framework-specific caching behavior.

Other frameworks

Frameworks such as Nuxt, SvelteKit, TanStack Start, and React Router may express caching through response headers, framework adapters, or runtime APIs.

When a framework produces standard cache directives or supported tag metadata, Easel applies the corresponding CDN behavior.

See the relevant framework guide for supported framework-specific behavior.

Runtime Cache invalidation

The Runtime Cache stores application values used inside Easel Functions. It is separate from the CDN cache, which stores complete HTTP responses.

A route can use both.

For example:

  1. A function reads product data from the Runtime Cache.
  2. It renders an HTTP response.
  3. Easel stores the completed response in the CDN cache.
  4. Both entries are associated with product:123.
  5. Purging that tag invalidates the underlying value and the rendered response.

This avoids serving a newly rendered page from stale application data.

Use the Runtime Cache API to assign tags when storing application values.

await cache.set("product:123", product, {
  tags: ["products", "product:123"],
});

The exact Runtime Cache API depends on the SDK version.

See Runtime Cache.

Purge scope

Cache operations should be scoped to the intended environment.

Production, preview, and development deployments use separate deployment contexts. A purge should not unintentionally remove cached content from unrelated deployments.

When initiating a purge, identify the relevant:

  • project
  • environment
  • deployment, when applicable
  • tag

A production purge should not normally invalidate independent preview deployments unless the purge explicitly targets shared application cache data.

Purge propagation

Easel records invalidation state across supported cache layers.

After a purge begins:

  1. matching entries are marked invalid
  2. later requests stop treating them as fresh
  3. the next request regenerates or retrieves updated content
  4. the replacement response can be cached under the new state

A purge does not guarantee that the replacement content already exists. It guarantees that invalidated content is no longer considered a valid fresh response.

Applications should ensure that the underlying data source is updated before initiating the purge.

Avoid purge races

Update the source of truth before invalidating its cached representations.

Recommended order:

1. Update database or content source
2. Confirm the update succeeded
3. Purge the relevant tag or path
4. Allow the next request to regenerate content

Do not purge first and update the database afterward. A request arriving between those operations could regenerate the cache using the old data.

For multi-step updates, complete the transaction before triggering invalidation.

Purging and browser caches

Easel can invalidate its shared cache, but it cannot directly remove a response already stored in a visitor’s browser.

Consider this policy:

Cache-Control: public, max-age=3600
CDN-Cache-Control: public, s-maxage=86400

Even after the Easel cache is purged, a browser may continue reusing its copy for up to one hour.

Use short browser lifetimes when content must respond quickly to CDN purges:

Cache-Control: public, max-age=0, must-revalidate
CDN-Cache-Control: public, s-maxage=86400

This allows Easel to cache the response for one day while browsers check for a current response on each visit.

Purging personalized content

User-specific and authenticated responses should generally not be stored in the shared CDN cache.

Use:

Cache-Control: private, no-store

When a response is correctly marked private, shared-cache purging is unnecessary because Easel does not reuse it across visitors.

Do not use cache tags as a substitute for appropriate privacy directives.

Common patterns

Product update

Tag product pages, API responses, and cached application data:

Cache-Tag: products product:123

After updating the product:

Purge tag: product:123

Purge products as well when the update affects collection pages.

Publishing an article

Before publication, keep the response private or uncached.

After publication:

Cache-Tag: articles article:842
CDN-Cache-Control: public, s-maxage=3600

When the article is edited:

Purge tag: article:842

Regenerating a landing page

For a route that changes periodically:

CDN-Cache-Control: public, s-maxage=300

No explicit purge is needed unless an update must appear before the five-minute lifetime expires. After the lifetime ends, the next request waits for a fresh response.

Organization-specific content

Include the organization identifier in the tag:

Cache-Tag: organization:acme organization:acme:dashboard

Purge only the affected organization:

Purge tag: organization:acme

Do not use a global tag when the update applies to only one organization.

Debugging revalidation

Inspect the response:

curl -I https://example.com/products

Relevant headers include:

X-Easel-Cache: HIT
CDN-Cache-Control: public, s-maxage=300
Cache-Tag: products

X-Easel-Cache is authoritative for whether Easel reused a cached response. An Age header may also appear on some responses, but it can be absent and is not required to interpret cache status.

After a successful purge, the next request commonly returns:

X-Easel-Cache: MISS

A later request may return:

X-Easel-Cache: HIT

Content remains cached after a purge

Check that:

  • the purged tag exactly matches the tag on the response
  • the purge targeted the correct project and environment
  • the request uses the expected hostname and query string
  • the browser is not reusing its own cached response
  • a framework is not serving content from another cache layer
  • the updated response was not regenerated using stale application data

A page regenerates with old content

The CDN entry may have been purged while the Runtime Cache or another data cache remained fresh.

Use a shared tag across the rendered response and its underlying cached values, or invalidate both layers explicitly.

Every request regenerates the response

Check whether:

  • the new response includes a positive shared-cache lifetime
  • the response contains Set-Cookie
  • the request contains Authorization
  • the route returns a cacheable status
  • the framework marks the route as dynamic
  • the cache is being purged repeatedly

An outdated response remains visible

After the shared-cache lifetime ends, Easel does not serve the expired entry as a cache hit. The next matching request waits for a fresh response.

If an outdated body is still visible, verify that:

  • the browser is not serving its own cached copy
  • a framework data cache or Runtime Cache entry was not left fresh
  • the purge or revalidation targeted the correct tag, path, and environment

Operational guidance

Prefer expiration when:

  • updates can appear within a predictable interval
  • occasional staleness is acceptable
  • the content is requested frequently enough to regenerate naturally

Prefer cache tags when:

  • one update affects several URLs or cache layers
  • content relationships are known by the application
  • updates must appear before the normal TTL expires

Prefer framework revalidation or dashboard cache clear when:

  • a specific route or deployment must refresh without a tag model
  • you need ISR or project-level invalidation

Avoid project-wide purges during normal application updates. Broad purges reduce cache hit rates and can cause many routes to regenerate simultaneously.