The Workers Lifecycle — Respond First, Finish Later
Every time someone follows a Hoplink, you want to record the click for the owner's statistics. But the visitor does not care about statistics; they want their redirect now. Making them wait while you send an analytics call wastes their time. Knowing how long a Worker lives, and what you may do after replying, solves this.
The rule
An invocation ends at the response — unless you hand work to
waitUntil.
Follow one request through its life:
- Wake. A request arrives at an edge location. If no isolate there has your code loaded, the runtime creates one — a matter of milliseconds.
- Handle. The runtime calls your
fetch(request, env, ctx). You mayawaitother services withfetch; time spent waiting on the network does not count as CPU time, which is the limit that matters most. - Respond. Once you return a
Response, the invocation is over. Unfinished promises may be cancelled. - Extend (optional).
ctx.waitUntil(promise)tells the runtime: "the response is sent, but keep me alive until this promise settles." - Idle and evict. The isolate may stay warm to serve the next request, or it may be discarded at any moment. Nothing in memory is promised to survive.
export default {
async fetch(request, env, ctx) {
const code = new URL(request.url).pathname.slice(1);
const target = "https://example.com/all-about-cats";
ctx.waitUntil(
fetch("https://stats.example/clicks", {
method: "POST",
body: JSON.stringify({ code, at: Date.now() }),
})
);
return Response.redirect(target, 302);
},
};The redirect goes out immediately; the stats call finishes in the background.
The fetch handler is not the only entry point. A Worker can also export scheduled (run on a cron schedule, such as a nightly cleanup) and queue (receive batches of messages, which you will meet in the last section). Each follows the same wake → handle → finish shape.
The shortcut
Sort every piece of work in a handler into one of two buckets by asking: does the visitor's response depend on this result? Yes means await it before returning. No means wrap it in ctx.waitUntil.
Look up the long URL
The redirect needs it, so
awaitit before responding.
Trap: starting a promise without awaiting it and without waitUntil — a "fire and forget" call. It may be cut off the moment the response is sent, so clicks silently go missing.
Drills
Answer fast — trust the rule.
What does ctx.waitUntil(promise) do?
A handler calls fetch(statsUrl) without await and without waitUntil, then returns. What is the risk?
Which piece of Hoplink work must be awaited before returning the redirect?
A Worker must purge expired links every night at 02:00. Which handler fits?
Remember
- An invocation ends at the response — unless you hand work to
waitUntil. - Shortcut: does the response depend on it? Await it. Otherwise,
waitUntil. - Trap: fire-and-forget promises that vanish when the invocation ends.
