Outline Technologies — SEO, AEO & GEO Agency
Back to Blog
TechnicalField Tested

How to Cache HTML at the Edge Without Serving Stale Pages

Most content delivery networks leave your pages uncached unless you ask, so every page view still travels to your server. We turned on page caching for our own site in October 2026 with one rule and one deploy step. This guide covers when it is safe, the exact settings we chose and why, how to purge without breaking pages, and the side effect almost nobody mentions: your server logs stop seeing most of your visitors, crawlers included.

Abd Shanti 12 min readOctober 18, 2026
In This Guide
The short answerWhen caching pages is safeWhat we measuredHow to set it upThe settings that matterPurging without breaking pagesWhat it does to crawler logsCommon mistakesFAQ

The Short Answer

Content delivery networks cache images, scripts and stylesheets out of the box, but not your pages. Cloudflare says it plainly: it does not cache HTML or JSON by default, and it decides by file extension, not by content type. To cache pages you add a rule that makes them eligible, give the edge copy a lifetime, tell browsers to check back every time, keep dynamic paths out of the rule, and clear the cache on every deploy. Done that way, the edge answers almost every request, the origin does a small fraction of the work, and nobody sees an old page after you publish.

The one sentence version

Cache pages at the edge for an hour, make browsers revalidate, exclude anything personal or dynamic, purge on every deploy, and expect your server logs to stop seeing most of your visitors.

When Caching Pages Is Safe

Page caching is safe when the same address returns the same page to everyone. Static sites, documentation, blogs and marketing pages usually qualify. Anything that changes per visitor does not: account pages, carts, pages that print a name, and any response that sets a cookie for the visitor. The test is simple. Open the page in two different browsers, one logged in if you have logins, and compare the HTML. If it differs, that path must stay out of the rule.

Kind of pageSafe to cache at the edge?Why
Static marketing pages and articlesYesIdentical for every visitor
Redirects between address variantsYes, with a lifetimeThey change only when you change them
Not found and server error responsesNoA cached error outlives the fix
Account, cart and checkout pagesNoPersonal to each visitor
Application programming interfaces and form endpointsNoDynamic answers and side effects
Pages that set a visitor cookieNoThe cookie would be served to everyone

What We Measured on Our Own Site

We turned page caching on for our own site on 13 October 2026. The site is a static export, so every visitor gets the same HTML, and the origin was already fast, answering in about five milliseconds. So the gain was never going to be a dramatic speed number for one page. It was load, consistency and resilience. Comparing the seven days before with the four days after, from the origin server log:

Measured at the origin, per day6 to 12 October14 to 17 October
Full page responses sent78750
Revalidations answered with no body2683
Page bytes sent19.6 MB1.1 MB
ChatGPT live agent page fetches the origin saw19.35.2

The first three rows are the point: the origin now sends about one twentieth of the page bytes it used to. The fourth row is the side effect most guides never mention, and it gets its own section below. Before the rule, the response header that reports cache status showed DYNAMIC on every page, meaning the network was not even trying to cache it. After, a fresh page shows MISS on the first request and HIT after that.

How to Set It Up, Step by Step

The steps below use Cloudflare cache rules, because that is what we run, but every CDN has the same four decisions: which requests, how long at the edge, how long in the browser, and how to clear it.

01

Confirm the pages are the same for everyone

Compare the HTML from two browsers and check that no page response sets a visitor cookie. Note every path that is personal or dynamic.

02

Create one cache rule for pages

Match your hostname and the page extensions: no extension, html, and any small data files your framework loads on navigation.

03

Exclude the dynamic paths

Leave out programming interface paths, webhook paths and the network control path, so form posts and tools always reach the origin.

04

Make matching requests eligible for cache

Choose eligible for cache, then set the edge lifetime to ignore the origin header and use a fixed time. We use one hour.

05

Set lifetimes by status code

Keep redirects for the same hour. Do not store not found or server error responses at all.

06

Make browsers revalidate

Set the browser setting to respect the origin, and have the origin send a no cache header on pages, so browsers ask again on every visit.

07

Purge on every deploy

Add a purge step to the deploy script after the build finishes, and fail the deploy loudly if the purge fails.

08

Verify from outside

Request a page twice and read the cache status header: MISS then HIT. Then load every asset the page references and confirm none is missing.

Step two has one detail for modern frameworks. Ours fetches small text files during navigation that describe the next page. We include that extension in the rule so the page and its navigation data are cached and cleared together. Caching one without the other can leave a visitor holding a page and navigation data from two different builds.

The Settings That Matter Most

SettingWhat we choseWhy
MatchOur hostname, page extensions, dynamic paths excludedPages only, nothing personal
Cache eligibilityEligible for cachePages are not cached without it
Edge lifetimeOne hour, ignoring the origin headerShort enough to be safe if a purge ever fails
Redirect lifetimeOne hourRedirects change only when we change them
Error lifetimeNot storedA cached error would outlive its fix
Browser lifetimeRespect the origin, which says revalidateNo visitor keeps an old page after a deploy
Tiered cacheOnFewer edge locations need to ask the origin

Watch the zone default for browsers

Our zone had a default browser cache lifetime of four hours. Left alone, it would have told browsers to keep an old page for four hours after every deploy, and no purge reaches a browser. Respecting a no cache header from the origin fixed it.

Reading the Cache Status Header

Every response through the network carries a header that says what the cache did with it, and a second header, Age, that says how many seconds the edge copy has existed. Reading the two together is the fastest way to confirm the rule works and to debug it when it seems not to. These are the values we saw on our own pages before and after the change.

Status you seeWhat it meansWhat to do
DYNAMICThe request did not match any rule that makes it cacheableCheck the rule match: hostname, extension, excluded paths
MISSEligible, but no edge copy existed yet, so the origin answeredRequest again; the second response should be a HIT
HITServed from the edge copy; Age shows how old it isNothing, this is the goal
REVALIDATEDThe edge copy expired, the origin confirmed nothing changedNormal once an hour per page with a one hour lifetime
A HIT right after a deployThe purge did not run or did not finishCheck the deploy log and purge again

One more check belongs in the verification step: request a page with a throwaway query parameter as well as without. Most setups include the query string in the cache key, so the parameter forces a MISS and shows you what the origin alone returns. If the two versions differ in anything other than the cache headers, something on the origin varies per request, and that page should not be cached.

Is It Worth It for a Small Site?

Honestly, the speed gain for a single page view can be small. When the origin already answers in a few milliseconds and the visitor is near it, the edge saves little time. The case for caching pages is elsewhere. The origin stops doing repeated work for identical requests, so a burst of crawlers or a link from a busy page no longer lands on one server. Visitors far from the origin get pages from a nearby copy. And the origin becomes a place you deploy to rather than a place every page view depends on. For us the twentyfold drop in page bytes was reason enough.

Purging Without Breaking Pages

The purge is the part that makes page caching safe, and it is also the part that can break things. A static build usually renames its script and style files on every deploy and deletes the old ones. If a cached page from the previous build survives, it points at files that no longer exist, and the page loads without its scripts or styles until the edge copy expires. That is why the edge lifetime should stay short, and why a failed purge must stop the deploy rather than be logged and ignored.

Purge methodUse it whenFree plan note
EverythingAfter a full site buildAvailable, limited to a few requests a minute per account
Single addressOne page changed outside a deployAvailable, generous limits
PrefixA section changed, such as the blogAvailable
HostnameOne of several hostnames changedAvailable
Cache tagPages share a tag you set at the originAvailable

Right after a purge every page is a miss, so the first visitor to each page waits for the origin and the origin briefly takes the full load again. For a small site that is seconds of extra work. For a large one, warming the most visited pages right after the purge, by requesting them once, spreads that load before real visitors arrive.

What Edge Caching Does to Your Crawler Logs

This is the side effect that catches people. Requests answered by the edge never reach your server, so they never reach your server log. If you measure search crawlers and AI agents from that log, as many teams do, your counts fall the day you turn caching on, even though nothing about the crawlers changed. On our site the ChatGPT live agent page fetches seen by the origin fell from 19.3 a day to 5.2, while the revalidation count rose by hundreds a day. The agents were being served from the copy.

Mark the date

Write down the day caching starts. Any chart that crosses that date compares two different measurements.

Count at the edge

After the change, take crawler and agent counts from the network analytics or request logs, which see every request.

Keep verifying names

Agent names are copied by scanners. Verification by published address ranges still applies, and it needs the real visitor address.

Search engines are unaffected in a useful way: they get the same page faster and more consistently, and your origin stops being the bottleneck when a crawler arrives in a burst. Our list of AI crawlers covers how to identify each agent, and the guide to JavaScript and AI crawlers explains why a cached, fully rendered static page is the easiest thing for any of them to read.

Common Mistakes

Caching everything

A rule without exclusions caches form endpoints, account pages and errors. Always list what stays dynamic.

Long edge lifetimes with no purge

A day long edge copy with no purge on deploy means a day of old pages after every change.

Forgetting the browser

A purge clears the edge, never the browser. Make browsers revalidate pages.

Reading the drop as a traffic loss

Origin logs fall when caching starts. Check the network analytics before reacting.

If you are also pinging search engines about new pages, the order matters: build, purge, then notify, so the engine fetches the new page and not a stale copy. Our IndexNow setup guide covers the notification step, and the technical SEO checklist has the rest of the deploy checks.

The Bottom Line

For a site whose pages are the same for everyone, caching HTML at the edge is one rule and one deploy step. Keep the edge lifetime short, keep errors and dynamic paths out, make browsers revalidate, and purge on every deploy with a hard failure if the purge fails. The origin will do a fraction of the work, pages will arrive consistently wherever visitors are, and your server log will stop telling you who visits. Move your counting to the edge on the same day you move your pages there.

Frequently Asked Questions

Does Cloudflare cache HTML by default?

No. Cloudflare says its CDN does not cache HTML or JSON by default and decides what to cache by file extension. To cache pages you create a cache rule that marks them eligible for cache and sets an edge lifetime.

How long should HTML be cached at the edge?

Short enough to be safe if a purge fails. We use one hour at the edge, purge everything on every deploy, keep redirects for an hour, never store error responses, and make browsers revalidate so no visitor keeps an old page.

How do I stop visitors seeing an old page after a deploy?

Purge the edge cache as a step of the deploy, after the build, and fail the deploy if the purge fails. Then make browsers revalidate pages by sending a no cache header from the origin, because a purge never reaches a browser.

Which pages should not be cached at the edge?

Any page that differs per visitor or sets a visitor cookie, such as account, cart and checkout pages, plus programming interface and form endpoints and error responses. Compare the HTML from two browsers to test a page before caching it.

Why did crawler traffic drop in my server logs after enabling caching?

Because requests answered by the edge never reach the origin. On our site, ChatGPT live agent fetches seen by the origin fell from 19.3 to 5.2 a day after page caching started, while revalidations rose by hundreds a day. Count crawlers from the CDN analytics instead.

Want a faster site without risking stale pages?

We set up edge caching, purge and verification as part of the deploy, check every path that must stay dynamic, and move your crawler measurement to where the requests land.

Get an AI visibility audit