Worker init runs twice
A Cloudflare Worker’s initialization effect runs twice. It runs when Alchemy declares deploy-time resources and when the Worker starts in an isolate, a separate execution environment. Those contexts do not have the same services.¶
On 2026-09-24, stage-specific rate-limit declarations used yield* Stage in the Worker initializer. The runtime did not have that deploy-time service, so production returned error 1101 for about three minutes.¶
The first change, commit 95687ec, added stage-specific rate-limit namespaces but evaluated them during Worker initialization. A revert backed it out; commit 6e85432 fixed it by declaring the resources only when globalThis.__ALCHEMY_RUNTIME__ !== true. The check now surrounds the rate-limit declarations and WorkerLoader declaration; the request-serving handler remains available at runtime.¶
apps/site/src/worker.ts shows the boundary. apps/site/test/worker-runtime-init.test.ts sets the runtime flag and provides only runtime bindings23. It starts the worker and checks that a request returns 404 rather than crashing.¶
Put 95687ec’s unguarded declarations back and the test fails with Service not found: Stage, the same failure production hit. Every earlier check exercised only the deploy side. Merge commit ae312a1 carries the fix into the merged branch.¶
See cartridges36 for the rule that each resource belongs to its Layer and the fence39 for the required tests that check this separation.¶
Sources
- fix(mischief): isolate rate limits by stage · joelhooks/rat-stack@95687ec · GitHub. GitHub joelhooks/rat-stack. Initial rate-limit change; used for the deploy-time service leak. Accessed 2026-10-01.
- Merge revert: stage rate limits broke Worker startup · joelhooks/rat-stack@9da5f9d · GitHub. GitHub joelhooks/rat-stack. Revert; used for the production rollback. Accessed 2026-10-01.
- fix(mischief): isolate rate-limit stages from runtime init · joelhooks/rat-stack@6e85432 · GitHub. GitHub joelhooks/rat-stack. Runtime guard fix; used for separating declarations from isolate startup. Accessed 2026-10-01.
- rat-stack/apps/site/test/worker-runtime-init.test.ts at main · joelhooks/rat-stack · GitHub. GitHub joelhooks/rat-stack. Runtime initialization test; used to reproduce missing deploy-time services. Accessed 2026-10-01.
Last changed 2026-10-10 in 978dccc. Source on GitHub. Change log.
Linked from
- Agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
Worker init runs twice — Alchemy Worker initialization runs in deploy and runtime contexts, so resource declarations need a boundary.
- Change log. What changed in the files served here, newest first.
Worker init runs twice — edited: docs: point live docs, skills and Brain pages at apps/site
- Full agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
- Purpose and boundaries of rat-stack (VISION.md). What this starter is for and what a useful copy should keep.
Worker init runs twice is what happens when you don’t.
- Rat Stack lore | rat-stack. Short, source-grounded notes on the ideas and decisions behind rat-stack.
Worker init runs twice — Alchemy Worker initialization runs in deploy and runtime contexts, so resource declarations need a boundary.
- Shared caches hold completed values. Keep pending request I/O out of isolate-scoped caches.
See Worker init runs twice for the initialization boundary and the fence for validation.¶
- Source change history (log.md). The generated change log as Markdown.
Worker init runs twice — edited: docs: point live docs, skills and Brain pages at apps/site
- There is no ISR on Cloudflare. SvelteKit's Vercel ISR setting does not configure Workers Cache; our local comparison did not prove cache reuse.
See Worker init runs twice for another boundary a local check can miss.¶