CLAUDE LABJP
2.1.273 — A round of connection work landed together: five opt-in headers for LLM gateways, and a notice when Claude Code stops trying to reconnect an MCP server09/29 — The date beside claude-sonnet-4-5 is 12 days out, but it is an earliest-possible estimate. The model is still Active, and public retirements get at least 60 days noticeMCP — People keep asking to reconnect a dropped server without ending the session. The disconnect is now announced, but reattaching is still something you do by handNEW — A scheduled task ran some days and not others. The cause was that only one folder had been bound to itWINDOWS — When Cowork fails on its very first task, check developer mode and the setup state before going looking for a causeHANDOFF — Before a long draft gets too heavy for one chat, decide on the three things the summary must carry into the next one2.1.273 — A round of connection work landed together: five opt-in headers for LLM gateways, and a notice when Claude Code stops trying to reconnect an MCP server09/29 — The date beside claude-sonnet-4-5 is 12 days out, but it is an earliest-possible estimate. The model is still Active, and public retirements get at least 60 days noticeMCP — People keep asking to reconnect a dropped server without ending the session. The disconnect is now announced, but reattaching is still something you do by handNEW — A scheduled task ran some days and not others. The cause was that only one folder had been bound to itWINDOWS — When Cowork fails on its very first task, check developer mode and the setup state before going looking for a causeHANDOFF — Before a long draft gets too heavy for one chat, decide on the three things the summary must carry into the next one
Articles/Claude Code
Claude Code/2026-08-19Intermediate

Fixing the Code Doesn't Evict a Broken Page From the Edge Cache

I shipped a fix and the broken page kept serving. The problem was not the code but the edge cache, which had stored a broken HTML response because the store decision looked only at the status code. Here is the integrity guard I now run before every cache write, and the thresholds I had to tune in production.

Claude Code253Cloudflare Workers16Edge CacheNext.js8Operations18

Premium Article

One morning I pushed a fix for a layout break on an article page. The build passed. The deploy succeeded. On my machine the page rendered correctly.

On a different device it was still broken.

A private window showed the same thing. Deploying again changed nothing. I reread the code several times looking for the mistake I must have made, and found nothing, because there was nothing to find. At that point I still had not suspected the cache. The response was returning 200.

The cache was the problem. A broken HTML response had been stored as a healthy one, and it was being served to everyone. My corrected code was sitting behind it, waiting for a request that never reached it.

The blind spot: broken pages that return 200

When you write a cache store decision, the natural thing to check is the status code. That is what I had done. Store 2xx, skip 4xx and 5xx. It is simple, and most of the time it is correct.

The trouble is that an application can be broken and still return 200.

In the Next.js App Router, an exception during rendering hands off to an error boundary (error.tsx or global-error.tsx), which renders a fallback UI. From HTTP's point of view that is a successful response: status 200. The same thing happens when only the article body fails to load and the surrounding shell renders fine. The page exists. There is nothing in it.

A status code tells you that a response was produced. It says nothing about whether that response is worth reading.

Response stateHTTP statusStatus-based decisionWhat the reader gets
Healthy page200StoreFine
Error boundary fallback200StoreBroken
Shell rendered, body empty200StoreBroken
Truncated HTML stream200StoreBroken
Server error500SkipBroken, but refetched

Rows two through four are the hole I fell into. Once stored, those responses stay until the TTL expires or someone purges them. The underlying fault may have lasted a few hundred milliseconds; the outage lasts hours.

What makes this hard to reason about is that the incident is not ongoing. It is frozen. Your logs are clean. You cannot reproduce it. And readers still see a broken page.

The trigger is almost always a momentary failure

It is worth explaining where the broken HTML came from.

The four sites I run are Next.js applications deployed on Cloudflare Workers. Article bodies are stored as separate HTML files and read through the static asset binding rather than bundled into the Worker, which is what keeps the bundle under the size limit. I wrote about that arrangement separately in the 62 MiB limit and content split architecture.

That design adds a step: fetching the body is a read that can fail. In the seconds right after a deploy, or occasionally for no visible reason, that read came back empty. It was rare. Not something I saw daily.

Rarity turned out to be no protection at all. A cache converts a rare failure into a permanent state. If one request in ten thousand fails and that one gets stored, the other nine thousand nine hundred and ninety-nine see the failure.

This asymmetry is easy to miss when you are reasoning about probability. I missed it.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
You will be able to decide what belongs in your cache based on whether the body is complete, not on whether the status code happens to be 200
You will be able to stop a one-in-ten-thousand render failure from becoming a page that every visitor sees, using a single guard at the write path
You will be able to tell within minutes whether a fix that appears not to work is a code problem or a cache problem
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Claude Code2026-04-21
Running Next.js on Cloudflare Workers in Production with Claude Code — Every Build Crisis, Cache Bug, and Automation Pattern We Solved
Running Next.js on Cloudflare Workers is not the same as Vercel. The 62 MiB bundle limit, ASSETS binding quirks, and edge cache personalization conflicts are real production hazards. Here's how Claude Code helped us solve each one.
Claude Code2026-04-06
Claude Code × Next.js 15 App Router Production: RSC, Server Actions, Auth, Testing & Deployment
The practical guide to production Next.js 15 App Router development with Claude Code. Covers RSC architecture decisions, Server Actions patterns, Auth.js v5, Vitest testing, and Cloudflare Workers deployment with practical code examples.
Claude Code2026-09-03
Aligning Log Timezones at Display Time, or Fixing Them at Write Time
AdMob, the store reports, and my own logs each ended the day at a different moment. Here is how I went back and forth between display-side and write-side timezone handling, and what I settled on.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links