Threads · note 03 / 4 · by Vorluno · Sep 21, 2026

Cloudflare kept the old face

The fix was in production for seven hours and the client kept seeing the bug. The CDN was doing exactly what we had asked it to do the day before.

What happened

A team photo was cropped wrong — the face cut off at the edge. We re-cropped it, committed, deployed. The client reloaded and reported the same cut face. git show said the file was right. curl said the server was right. The browser said otherwise.

The cause

The day before we had written the cache rules on purpose: HTML bypasses the cache (so deploys are instant), /_next/static/ is cached for a year (content-hashed), and images under /equipo/, /video/ and /vorluno/ are cached for a day. The photo lives under /equipo/ with the same file name before and after the fix. Cloudflare served the old bytes with cf-cache-status: HIT and an Age of 25 514 seconds. Correct behaviour, wrong outcome.

The fix, twice

Immediately: purge the three URLs through the API. Permanently: the choice is between content-hashed names (the file changes name when its bytes change — what Next does for /_next/static) and purge-on-change written into the script that produces the file. We went with the second for the team photos, because their names are part of the page's data model, and documented it where the file is generated:

// scripts/equipo.ts
// Al cambiar una foto: purgar https://vorluno.dev/equipo/ en Cloudflare (la regla cachea /equipo/ un día).

The rule we kept

Every cache rule is a promise about when a URL may change. If a file can change without changing its name, either the rule is wrong or the deploy has to purge. Write down which.

// next noteSatori does not read woff2