Cloudflare Workers
Run Checkrd at the edge — policy enforcement in workerd with sub-millisecond overhead.
Cloudflare Workers
Checkrd is built to run at the edge. The WASM core is wasm32-wasip1 — a clean format Cloudflare Workers' runtime (workerd) loads natively via WebAssembly.compile. No node:* shims, no Node polyfills.
Install
npm install checkrdQuickstart
import { withCheckrd } from "checkrd/integrations/cloudflare";
export default withCheckrd<Env>(
async (request, env, ctx, checkrd) => {
// Your worker logic. `checkrd` is the initialized engine + sink.
return new Response("ok");
},
{
apiKey: (env) => env.CHECKRD_API_KEY, // pulled from Cloudflare secrets
agentId: "edge-worker",
policyUrl: (env) => env.CHECKRD_POLICY_URL, // optional — fetch policy from R2 or KV
},
);withCheckrd is a HOC that:
- Initializes the WASM engine on first request and caches it across the worker's lifetime (Workers reuse isolates).
- Loads the policy from a URL (R2, KV, or external) — works around Workers having no filesystem.
- Passes the live
checkrdcontext to your handler so you canwrapoutbound clients or attach the AI SDK middleware.
With the Vercel AI SDK
import { withCheckrd } from "checkrd/integrations/cloudflare";
import { checkrdMiddleware } from "checkrd/integrations/ai-sdk";
import { generateText, wrapLanguageModel } from "ai";
import { openai } from "@ai-sdk/openai";
export default withCheckrd<Env>(
async (request, env, ctx, checkrd) => {
const model = wrapLanguageModel({
model: openai("gpt-4o"),
middleware: checkrdMiddleware({
engine: checkrd.engine,
enforce: true,
agentId: "edge-worker",
sink: checkrd.sink,
}),
});
const { text } = await generateText({
model,
prompt: await request.text(),
});
return new Response(text);
},
{ apiKey: (env) => env.CHECKRD_API_KEY, agentId: "edge-worker" },
);Loading the policy
Workers have no filesystem. Three options:
- Embed at build time — pass a YAML string in
policy:. - Cloudflare R2 — store
policy.yamlin an R2 bucket; passpolicyUrl: env => env.POLICY_URL. - Cloudflare KV — store the policy in KV; load it in the handler before calling Checkrd's reload API.
For policies that change frequently, prefer Checkrd's signed-bundle SSE (controlPlaneUrl: "https://api.checkrd.io") — the engine receives DSSE-verified bundles over a long-lived stream and reloads in place without a worker restart.
Telemetry
The default sink in Workers buffers events in memory and flushes via ctx.waitUntil(...) at the end of each request. No daemon thread, no polling — fits the workerd lifecycle.
{
apiKey: (env) => env.CHECKRD_API_KEY,
agentId: "edge-worker",
// sink is auto-configured against env.CHECKRD_API_KEY; override only if needed.
}Caveats
- No
node:*imports. Don't passpolicy: fs.readFileSync(...)— that path is Node-only. Usepolicy: "..."(string),policyUrl, orpolicyBytes(Uint8Array). - Cold start. First request loads the WASM (~10ms cold). Subsequent requests reuse the compiled module across the isolate's lifetime. For sub-ms p99, keep your worker hot via Cloudflare's Smart Placement.
- Cloudflare-specific globals. The Cloudflare adapter uses
crypto.subtlefor SHA-256 (the WASM integrity check) andWebAssembly.compilefor module loading — both are workerd built-ins. No polyfill required.