Examples
These examples show complete Cache patterns you can adapt inside Layeron route handlers.
API Response Cache
Section titled “API Response Cache”Cache a public list endpoint and purge it after writes.
const apiCache = cache({ name: "public-api", ttlSeconds: 60, tags: ["products"],})
app.use(apiCache)
app.get("/api/products", async (request) => { const cached = await apiCache.match(request)
if (cached) { return cached }
const products = await listProducts() const response = Response.json({ products })
await apiCache.put(request, response.clone(), { tags: ["products"], })
return response})
app.post("/api/products", async (request) => { const input = await request.json() const product = await createProduct(input)
await apiCache.purge({ tags: ["products"], })
return Response.json({ product }, { status: 201 })})Detail Page With Precise Tags
Section titled “Detail Page With Precise Tags”Attach list and item tags to detail responses.
app.get("/api/products/:id", async (request) => { const pathSegments = new URL(request.url).pathname.split("/") const id = pathSegments[3] const cached = await apiCache.match(request)
if (cached) { return cached }
const product = await findProduct(id)
if (!product) { return Response.json({ error: "Missing product" }, { status: 404 }) }
const response = Response.json({ product })
await apiCache.put(request, response.clone(), { tags: ["products", `product:${id}`], ttlSeconds: 120, })
return response})
app.patch("/api/products/:id", async (request) => { const pathSegments = new URL(request.url).pathname.split("/") const id = pathSegments[3] const input = await request.json() const product = await updateProduct(id, input)
await apiCache.purge({ tags: ["products", `product:${id}`], })
return Response.json({ product })})Localized Content
Section titled “Localized Content”Use vary when the same path can produce different languages.
const contentCache = cache({ name: "content", ttlSeconds: 300, vary: ["accept-language"],})
app.use(contentCache)
app.get("/api/homepage", async (request) => { const cached = await contentCache.match(request)
if (cached) { return cached }
const language = request.headers.get("accept-language") ?? "en" const page = await loadHomepage(language) const response = Response.json({ page })
await contentCache.put(request, response.clone(), { tags: ["homepage"], })
return response})Webhook-Driven Invalidation
Section titled “Webhook-Driven Invalidation”Purge cached content after a CMS or commerce webhook.
app.post("/webhooks/catalog", async (request) => { const event = await verifyCatalogWebhook(request)
if (event.type === "product.updated") { await apiCache.purge({ tags: ["products", `product:${event.productId}`], }) }
if (event.type === "catalog.rebuilt") { await apiCache.purge({ tags: ["products"], }) }
return Response.json({ ok: true })})