| name | edge-patterns-advanced |
| description | Advanced Edge Computing patterns — streaming responses (TransformStream, Server-Sent Events), edge caching (Cache API, stale-while-revalidate), Miniflare testing, and common edge runtime mistakes (Node.js APIs, large npm packages, synchronous computation). |
Edge Patterns — Advanced
This skill extends edge-patterns with streaming, caching, testing, and anti-patterns. Load edge-patterns first.
When to Activate
- Streaming large responses through a Cloudflare Worker
- Implementing edge caching with stale-while-revalidate
- Testing Workers locally with Miniflare
- Debugging "not supported in edge runtime" errors for Node.js API usage
Streaming Responses
export default {
async fetch(request: Request): Promise<Response> {
const upstream = await fetch('https://slow-api.example.com/data');
const { readable, writable } = new TransformStream({
transform(chunk, controller) {
const text = new TextDecoder().decode(chunk);
controller.enqueue(new TextEncoder().encode(text.toUpperCase()));
},
});
upstream.body!.pipeTo(writable);
return new Response(readable, {
headers: {
'Content-Type': 'text/plain',
'Transfer-Encoding': 'chunked',
},
});
},
};
function* generateEvents() {
for (let i = 0; i < 10; i++) {
yield `data: ${JSON.stringify({ count: i })}\n\n`;
}
}
export default {
fetch(): Response {
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
for (const event of generateEvents()) {
controller.enqueue(encoder.encode(event));
await new Promise(r => setTimeout(r, 1000));
}
controller.close();
},
});
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
},
});
},
};
Edge Caching
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const cache = caches.default;
const cacheKey = new Request(request.url, { method: 'GET' });
const cached = await cache.match(cacheKey);
if (cached) {
return new Response(cached.body, {
...cached,
headers: { ...cached.headers, 'X-Cache': 'HIT' },
});
}
const response = await fetch(request);
const toCache = new Response(response.body, response);
toCache.headers.set('Cache-Control', 'public, max-age=3600');
toCache.headers.set('X-Cache', 'MISS');
ctx.(cache.(cacheKey, toCache.()));
toCache;
},
};
async function swr(
cacheKey: Request,
fetchFn: () => Promise<Response>,
maxAge: number,
staleAge: number,
ctx: ExecutionContext
): Promise<Response> {
const cache = caches.default;
const cached = await cache.match(cacheKey);
if (cached) {
const age = parseInt(cached.headers.get('X-Cache-Age') ?? '0');
if (age < maxAge) return cached;
if (age < staleAge) {
ctx.waitUntil(
fetchFn().then(fresh => {
fresh.headers.set('X-Cache-Age', '0');
return cache.put(cacheKey, fresh);
})
);
return cached;
}
}
const fresh = await ();
toCache = (fresh., fresh);
toCache..(, );
ctx.(cache.(cacheKey, toCache.()));
toCache;
}
Testing — Miniflare
import { Miniflare } from 'miniflare';
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
describe('Worker', () => {
let mf: Miniflare;
beforeAll(async () => {
mf = new Miniflare({
scriptPath: './src/index.ts',
kvNamespaces: ['MY_KV'],
d1Databases: ['MY_DB'],
bindings: { MY_SECRET: 'test-secret' },
});
});
afterAll(() => mf.dispose());
it('returns health check', async () => {
const res = await mf.dispatchFetch('http://localhost/api/health');
expect(res.status).toBe(200);
const body = await res.json();
expect(body).toEqual({ status: 'ok' });
});
it('reads from KV', () => {
kv = mf.();
kv.(, .({ : }));
res = mf.();
(res.).();
});
});
npm install -D miniflare vitest
vitest run
Common Mistakes
import { readFileSync } from 'fs';
const data = await fetch(new URL('./data.json', import.meta.url)).then(r => r.json());
import moment from 'moment';
import { format } from 'date-fns/format';
export default {
fetch(): Response {
const result = heavySync(largeData);
return Response.json(result);
}
}
Reference
edge-patterns — runtime constraints, Cloudflare Workers (KV/D1/R2/Durable Objects), Vercel Edge Middleware, Deno Deploy
serverless-patterns — cold starts, Step Functions, Lambda Powertools, idempotency
wasm-patterns — run Rust WASM in Cloudflare Workers