“I need to run something later from a Cloudflare Worker but there's no setTimeout that survives”
Schedule a background job from a Cloudflare Worker
Workers can't keep a timer alive past the response. Make one fetch to Fliq with a future scheduled_at and Fliq calls your Worker back on time — no Durable Objects, no Queues.
A Cloudflare Worker’s execution context dies when the response is sent. You can’t hold a timer for 30 minutes, and reaching for Durable Objects just to “call this URL later” is a lot of machinery. Make one fetch to Fliq instead: it stores the fire time and POSTs back to your Worker on schedule.
The request
From inside the Worker, create a job whose url points at a route on the same Worker. Store your Fliq token as a Worker secret (wrangler secret put FLIQ_API_TOKEN).
curl -X POST https://api.fliq.sh/jobs \
-H "Authorization: Bearer fliq_sk_your_token" \
-H "Content-Type: application/json" \
-d '{
"url": "https://my-worker.example.workers.dev/api/send-welcome",
"http_method": "POST",
"scheduled_at": "2026-06-12T10:30:00Z",
"headers": { "Content-Type": "application/json" },
"body": "{\"email\":\"user@example.com\"}",
"max_retries": 3
}' export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === "/api/signup") {
// 30 minutes after signup, have Fliq call us back.
await fetch("https://api.fliq.sh/jobs", {
method: "POST",
headers: {
"Authorization": `Bearer ${env.FLIQ_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: "https://my-worker.example.workers.dev/api/send-welcome",
http_method: "POST",
scheduled_at: new Date(Date.now() + 30 * 60_000).toISOString(),
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: "user@example.com" }),
max_retries: 3,
}),
});
return Response.json({ ok: true });
}
if (url.pathname === "/api/send-welcome") {
const { email } = await request.json();
// ... send the email ...
return Response.json({ sent: true });
}
return new Response("Not found", { status: 404 });
},
}; No Durable Objects, no Queues, no wrangler.toml cron triggers — just one outbound fetch.
What Fliq handles for you
- The timer Workers don’t have. The fire time lives in Fliq’s Postgres, well outside the Worker’s request lifetime, so the callback survives the isolate being torn down.
- Retries on the callback. If your Worker route is briefly erroring when Fliq calls back,
max_retrieswith backoff covers it. - Dynamic schedules. Create, change, or cancel jobs by API at runtime — unlike
wrangler.tomlcron triggers, which are fixed at deploy and can’t carry a dynamic payload. - History. Every callback attempt is recorded, so a misbehaving handler is visible in the dashboard rather than lost in Worker logs.
Related
- How to schedule background jobs in Cloudflare Workers — the full walkthrough
- Jobs & Schedules — the job object
- Delay a job N hours
Reference: /docs/jobs-and-schedules