← Cloudflare Workers / workers / cache
Vymazávání mezipaměti
Váš Worker může kdykoli invalidovat vlastní odpovědi uložené v cache pomocí purge API. Purge se hodí ve chvíli, kdy se data změní a nová hodnota je důležitější než výkonnostní výhoda plynoucí z dalšího vracení odpovědi z cache: například po aktualizaci obsahu, po akci uživatele nebo po webhooku z nadřazeného systému.
Protože Workers Caching je cache vašeho Workeru, purge je omezen na Worker, který cache vlastní. V rámci Workeru je purge dále omezen na entrypoint která volala purge(). Worker se nemůže dostat do cache jiného Workeru, vstupní bod se nemůže dostat do cache jiného vstupního bodu a žádné čištění na úrovni zóny (přes dashboard, API, nebo Terraform) ovlivňuje obsah Workers Caching.
Dva způsoby, jak volat purge
Existují dva rovnocenné způsoby, jak zevnitř Workeru vyvolat purge:
ctx.cache.purge(...): dostupné v execution contextu předávaném každému handleru. Použijte to, pokud už mátectxv rozsahu.cache.purge(...): importováno zcloudflare:workers. Použijte to, když chcete volat purge z kódu, který nedostáváctx: například pomocný modul sdílený mezi více handlery nebo adaptér frameworku, který execution context neprovléká svým vnitřním kódem.
Obě podoby volají stejné API a chovají se shodně. Vyberte tu, která se pro váš kód lépe čte.
import { cache } from "cloudflare:workers";
export default {
async fetch(request, env, ctx) {
// Using the module import — no need to thread ctx through helper functions.
await cache.purge({ tags: ["blog-posts"] });
// Equivalent, using ctx directly:
// await ctx.cache.purge({ tags: ["blog-posts"] });
return new Response("Purged", { status: 200 });
},
};import { cache } from "cloudflare:workers";
export default {
async fetch(request, env, ctx): Promise<Response> {
// Using the module import — no need to thread ctx through helper functions.
await cache.purge({ tags: ["blog-posts"] });
// Equivalent, using ctx directly:
// await ctx.cache.purge({ tags: ["blog-posts"] });
return new Response("Purged", { status: 200 });
},
} satisfies ExportedHandler;Zbytek této stránky používá ctx.cache.purge(...) ve většině příkladů, protože tyto příklady již mají ctx v rozsahu. Pokud dáváte přednost formě importu, nahraďte cache.purge(...), nothing else changes.
Režimy vymazávání
purge() přijímá buď purgeEverything: true samostatně, nebo jeden či oba z tags a pathPrefixes:
| Pole | Vymazání | Rozsah |
|---|---|---|
tags |
Každá odpověď uložená v mezipaměti a označená některou ze zadaných hodnot pomocí Cache-Tag. |
Podle entrypointu |
pathPrefixes |
Každá odpověď uložená v mezipaměti, jejíž cesta požadavku začíná některým ze zadaných prefixů. | Podle entrypointu |
purgeEverything |
Každá odpověď uložená v mezipaměti pro vstupní bod, který zavolal purge(). |
Podle entrypointu |
purgeEverything je exkluzivní, kombinujte tags a pathPrefixes v jednom volání, pokud chcete, ale nepředávejte ani jedno společně s purgeEverything.
Všechny tři režimy jsou omezeny na entrypoint která volala purge(). Vyčištění z PublicAPI neovlivňuje odpovědi uložené v mezipaměti pomocí AdminAPI, i když sdílí názvy tagů nebo prefixy cest. Chcete-li provést invalidaci napříč všemi vstupními body Workeru, zavolejte purge() z každého vstupního bodu.
Vrácený promise se vyřeší objektem výsledku, který můžete prozkoumat, abyste ověřili úspěch nebo ošetřili chyby, viz Návratová hodnota.
Vymažte mezipaměť po zápisu voláním ctx.cache.purge() na konci každého handleru, který upravuje data:
export default {
async fetch(request, env, ctx) {
if (request.method === "POST") {
const body = await request.json();
// Mutate your data source (D1, KV, an origin, and so on), then invalidate
// every cached response tagged for this post.
await ctx.cache.purge({
tags: [`post-${body.postId}`, "post-list"],
});
return new Response("Updated", { status: 200 });
}
// Handle cacheable reads here.
return new Response("Hello", {
headers: { "Cache-Control": "public, max-age=3600" },
});
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
if (request.method === "POST") {
const body = await request.json<{ postId: string }>();
// Mutate your data source (D1, KV, an origin, and so on), then invalidate
// every cached response tagged for this post.
await ctx.cache.purge({
tags: [`post-${body.postId}`, "post-list"],
});
return new Response("Updated", { status: 200 });
}
// Handle cacheable reads here.
return new Response("Hello", {
headers: { "Cache-Control": "public, max-age=3600" },
});
},
} satisfies ExportedHandler;Pole můžete kombinovat v jediném volání. Například purge({ tags: ["blog-posts"], pathPrefixes: ["/blog/"] }) vymaže (purge) vše, co odpovídá buď tag nebo path-prefix, pole se sjednocují, nikoli protínají. Použijte to v případě, kdy jedna logická invalidace ovlivňuje odpovědi označené více schématy.
export default {
async fetch(request, env, ctx) {
// Combined call: invalidates everything tagged "blog-posts" AND
// everything under /blog/ in a single round-trip.
await ctx.cache.purge({
tags: ["blog-posts"],
pathPrefixes: ["/blog/"],
});
return new Response("Purged", { status: 200 });
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
// Combined call: invalidates everything tagged "blog-posts" AND
// everything under /blog/ in a single round-trip.
await ctx.cache.purge({
tags: ["blog-posts"],
pathPrefixes: ["/blog/"],
});
return new Response("Purged", { status: 200 });
},
} satisfies ExportedHandler;Vymazání podle tagu
Značky se k odpovědím připojují prostřednictvím Cache-Tag hlavička odpovědi a později se dá vyčistit podle názvu. Jde o nejflexibilnější a nejběžněji používanou metodu čištění.
Přidávání tagů při zápisu
export default {
async fetch(request) {
const url = new URL(request.url);
const postId = url.pathname.split("/").pop() ?? "unknown";
const body = { id: postId, title: `Post ${postId}` };
return new Response(JSON.stringify(body), {
headers: {
"Content-Type": "application/json",
"Cache-Control": "public, max-age=3600",
"Cache-Tag": `post,post-${postId},blog`,
},
});
},
};export default {
async fetch(request): Promise<Response> {
const url = new URL(request.url);
const postId = url.pathname.split("/").pop() ?? "unknown";
const body = { id: postId, title: `Post ${postId}` };
return new Response(JSON.stringify(body), {
headers: {
"Content-Type": "application/json",
"Cache-Control": "public, max-age=3600",
"Cache-Tag": `post,post-${postId},blog`,
},
});
},
} satisfies ExportedHandler; Cache-Tag hlavičky je seznam tagů oddělených čárkami. Cloudflare tuto hlavičku před vrácením odpovědi klientům odstraní.
Hodnoty značek musí být tisknutelné ASCII (bez mezer, bez Unicode), každý tag má nejvýše 1024 znaků dlouhý a odpověď může nést až 1000 štítků. Shoda tagů při purge je bez rozlišování velikosti písmen, takže Foo a foo vymažou (purge) stejnou sadu odpovědí. Neplatné štítky jsou při ukládání tiše zahazovány, odpověď se přesto uloží do cache se zbývajícími platnými štítky. Viz Limity cache tagů pro úplný seznam.
Spustit purge
export default {
async fetch(request, env, ctx) {
const postId = new URL(request.url).searchParams.get("id");
if (!postId) return new Response("Missing id", { status: 400 });
await ctx.cache.purge({ tags: [`post-${postId}`] });
return new Response("Purged", { status: 200 });
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
const postId = new URL(request.url).searchParams.get("id");
if (!postId) return new Response("Missing id", { status: 400 });
await ctx.cache.purge({ tags: [`post-${postId}`] });
return new Response("Purged", { status: 200 });
},
} satisfies ExportedHandler;Rozsah značek napříč entrypointy
Značky jsou vázány na entrypoint, který zavolal purge(). Tag s názvem user-42 použitá u odpovědí ve dvou různých entrypointech je ne zneplatněny jedním purge({ tags: ["user-42"] }) volání: ovlivňuje pouze entrypoint, z něhož volání pochází. Pokud potřebujete zneplatnit stejný tag napříč několika entrypointy, zavolejte purge() z každého vstupního bodu, nebo purge volání centralizujte do sdíleného vstupního bodu, který cachuje každou odpověď, kterou budete později potřebovat invalidovat.
Použijte hierarchické tagy
Chcete-li jedním voláním zneplatnit skupiny souvisejících odpovědí, označte každou odpověď více štítky reprezentujícími každou úroveň hierarchie, do které patří, tzv. „soft tags“:
export default {
async fetch(request) {
const path = new URL(request.url).pathname;
// Build a list of hierarchical tags for the current path.
// A response at /blog/2025/02/hello gets tags for:
// _path:/blog/, _path:/blog/2025/, _path:/blog/2025/02/, _path:/blog/2025/02/hello
const segments = path.split("/").filter(Boolean);
const tags = segments.map(
(_, i) => `_path:/${segments.slice(0, i + 1).join("/")}/`,
);
const body = `<!doctype html><title>${path}</title>`;
return new Response(body, {
headers: {
"Content-Type": "text/html",
"Cache-Control": "public, max-age=3600",
"Cache-Tag": tags.join(","),
},
});
},
};export default {
async fetch(request): Promise<Response> {
const path = new URL(request.url).pathname;
// Build a list of hierarchical tags for the current path.
// A response at /blog/2025/02/hello gets tags for:
// _path:/blog/, _path:/blog/2025/, _path:/blog/2025/02/, _path:/blog/2025/02/hello
const segments = path.split("/").filter(Boolean);
const tags = segments.map(
(_, i) => `_path:/${segments.slice(0, i + 1).join("/")}/`,
);
const body = `<!doctype html><title>${path}</title>`;
return new Response(body, {
headers: {
"Content-Type": "text/html",
"Cache-Control": "public, max-age=3600",
"Cache-Tag": tags.join(","),
},
});
},
} satisfies ExportedHandler;Vymazávání tagu _path:/blog/2025/ pak zneplatní každou uloženou odpověď, jejíž URL začíná na /blog/2025/.
Limity počtu, délky a znakové sady tagů najdete v Limity cache tagů.
Vymazání specifické pro verzi
Ve výchozím nastavení Workers Caching rozděluje cache podle verze Workeru, takže každé nasazení začíná se studenou cache a purge pro konkrétní verzi není potřeba. Tato část platí pouze v případě, že máte povoleno cache.cross_version_cache pro sdílení uložených odpovědí mezi verzemi. V takovém případě může být odpověď zapsaná verzí A stále doručována i po nasazení verze B, a proto může být užitečné vymazat záznamy zapsané konkrétní verzí, například po rollbacku. Za tímto účelem označte každou odpověď verzí, která ji vytvořila, a tento tag později vymažte.
Přidejte vazba metadat verze do konfigurace Wrangler:
{
"name": "my-worker",
"main": "src/index.ts",
// Set this to today's date
"compatibility_date": "2026-08-28",
"cache": { "enabled": true, "cross_version_cache": true },
"version_metadata": { "binding": "CF_VERSION_METADATA" },
}name = "my-worker"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-08-28"
[cache]
enabled = true
cross_version_cache = true
[version_metadata]
binding = "CF_VERSION_METADATA"Poté připojte ID verze na začátek svých značek:
export default {
async fetch(request, env, ctx) {
const { id: versionId } = env.CF_VERSION_METADATA;
const postId = new URL(request.url).pathname.split("/").pop() ?? "unknown";
return new Response(JSON.stringify({ id: postId }), {
headers: {
"Content-Type": "application/json",
"Cache-Control": "public, max-age=3600",
// Include the version ID as a tag so you can purge by version later.
"Cache-Tag": `post,post-${postId},v:${versionId}`,
},
});
},
};interface Env {
CF_VERSION_METADATA: WorkerVersionMetadata;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
const { id: versionId } = env.CF_VERSION_METADATA;
const postId = new URL(request.url).pathname.split("/").pop() ?? "unknown";
return new Response(JSON.stringify({ id: postId }), {
headers: {
"Content-Type": "application/json",
"Cache-Control": "public, max-age=3600",
// Include the version ID as a tag so you can purge by version later.
"Cache-Tag": `post,post-${postId},v:${versionId}`,
},
});
},
} satisfies ExportedHandler<Env>;Pokud chcete zneplatnit vše, co zapsala konkrétní verze, například po rollbacku, vymažte tag této verze:
export default {
async fetch(request, env, ctx) {
const versionId = new URL(request.url).searchParams.get("version");
if (!versionId) return new Response("Missing version", { status: 400 });
await ctx.cache.purge({ tags: [`v:${versionId}`] });
return new Response("Purged", { status: 200 });
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
const versionId = new URL(request.url).searchParams.get("version");
if (!versionId) return new Response("Missing version", { status: 400 });
await ctx.cache.purge({ tags: [`v:${versionId}`] });
return new Response("Purged", { status: 200 });
},
} satisfies ExportedHandler;Vymazání podle prefixu cesty
pathPrefixes zneplatní každou odpověď uloženou v mezipaměti, jejíž cesta požadavku začíná jedním ze zadaných prefixů:
export default {
async fetch(request, env, ctx) {
// Invalidate everything under /blog/2025/ for the current entrypoint.
await ctx.cache.purge({
pathPrefixes: ["/blog/2025/"],
});
return new Response("Purged", { status: 200 });
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
// Invalidate everything under /blog/2025/ for the current entrypoint.
await ctx.cache.purge({
pathPrefixes: ["/blog/2025/"],
});
return new Response("Purged", { status: 200 });
},
} satisfies ExportedHandler;Položky v pathPrefixes jsou cesty, nikoli úplné adresy URL. Prefix nesmí obsahovat schéma, hostitele, řetězec dotazu ani fragment: pokud předáte například https://example.com/blog/ je neplatný vstup, nikoli prefix, který jednoduše neodpovídá. Úvodní lomítko je volitelné (/images a images se zachází stejně), ale doporučuje se kvůli přehlednosti.
pathPrefixes se vztahuje pouze na vstupní bod, který provádí volání purge. purge({ pathPrefixes: ["/blog/"] }) z PublicAPI neovlivní odpovědi uložené v cache AdminAPI, i když jejich cesty také začínají /blog/.
Vymazání jedné URL adresy
Neexistuje samostatný režim "purge by URL". Chcete-li zneplatnit jednu uloženou URL adresu, předejte její cestu jako jednoprvkové pathPrefixes pole:
export default {
async fetch(request, env, ctx) {
// Invalidate the cached response for exactly /blog/2026/hello-world.
await ctx.cache.purge({
pathPrefixes: ["/blog/2026/hello-world"],
});
return new Response("Purged", { status: 200 });
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
// Invalidate the cached response for exactly /blog/2026/hello-world.
await ctx.cache.purge({
pathPrefixes: ["/blog/2026/hello-world"],
});
return new Response("Purged", { status: 200 });
},
} satisfies ExportedHandler;Protože pathPrefixes se shoduje se začátkem cesty požadavku, předání celé cesty odpovídá pouze této cestě, plus všem cestám, které ji rozšiřují (například /blog/2026/hello-world-2). Pokud potřebujete sémantiku přesné shody bez rizika zbytečného purge, použijte značka místo toho.
Vymazání veškerého obsahu
Zneplatní všechny odpovědi uložené v cache volajícím entrypointem:
export default {
async fetch(request, env, ctx) {
await ctx.cache.purge({ purgeEverything: true });
return new Response("Purged", { status: 200 });
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
await ctx.cache.purge({ purgeEverything: true });
return new Response("Purged", { status: 200 });
},
} satisfies ExportedHandler;Používejte to jen výjimečně. Vymazání celé cache způsobí, že všechny následující požadavky cache minou, dokud se znovu nenaplní, což dočasně zvýší zátěž Workeru i všech upstream služeb, které volá.
Propagace vymazávání
Vymazání vyvolaná ctx.cache.purge() použijte Cloudflare Instant Purge infrastruktuře a šíří se globálně se stejnými zárukami jako purge na úrovni zóny.
Návratová hodnota
purge() se přeloží na objekt výsledku. Zkontrolujte success pro potvrzení, že vyčištění bylo přijato, a pro kontrolu errors pokud nebyl:
export default {
async fetch(request, env, ctx) {
const result = await ctx.cache.purge({ tags: ["blog-posts"] });
if (!result.success) {
console.error("Cache purge failed", result.errors);
return new Response("Purge failed", { status: 500 });
}
return new Response("Purged", { status: 200 });
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
const result = await ctx.cache.purge({ tags: ["blog-posts"] });
if (!result.success) {
console.error("Cache purge failed", result.errors);
return new Response("Purge failed", { status: 500 });
}
return new Response("Purged", { status: 200 });
},
} satisfies ExportedHandler;V případě selhání každá chyba v errors nese číselný code a člověku srozumitelný message můžete zaznamenat nebo předat volajícímu.
Limity počtu požadavků
purge() používá stejný systém omezování rychlosti jako Cloudflare zone purge API. Protože je ale Workers Caching svázán s Workerem, nikoli se zónou, Workers Cache vždy používá Limity úrovně Free popsané v Dostupnost a limity, bez ohledu na tarif vašeho účtu nebo zóny. Když je purge omezen rychlostním limitem, success je false a errors obsahuje položku popisující odmítnutí.