# Worker init runs twice

> For agents: start with the [agent guide](https://ratstack.sh/llms.txt). Every page is Markdown by default; add `Accept: text/html` for HTML.

New on /news: [tla-ts 0.0.9 adds TLC's -continue](/news).

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](https://github.com/joelhooks/rat-stack/commit/95687ec906a6b4cde99a5b8e5df77115695833a8), added stage-specific rate-limit namespaces but evaluated them during Worker initialization. [A revert](https://github.com/joelhooks/rat-stack/commit/9da5f9d) backed it out; [commit 6e85432](https://github.com/joelhooks/rat-stack/commit/6e85432034400df8e49a9354a4cab1246d7cece0) 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 bindings. 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](https://github.com/joelhooks/rat-stack/commit/ae312a13e91c395a97404a565871d7a96de11388) carries the fix into the merged branch.

See [cartridges](/lore/cartridges) for the rule that each resource belongs to its Layer and [the fence](/lore/the-fence) for the required tests that check this separation.

## Sources

1. [fix(mischief): isolate rate limits by stage · joelhooks/rat-stack@95687ec · GitHub](https://github.com/joelhooks/rat-stack/commit/95687ec906a6b4cde99a5b8e5df77115695833a8)
   GitHub joelhooks/rat-stack. Initial rate-limit change; used for the deploy-time service leak. Accessed 2026-10-01.

2. [Merge revert: stage rate limits broke Worker startup · joelhooks/rat-stack@9da5f9d · GitHub](https://github.com/joelhooks/rat-stack/commit/9da5f9d)
   GitHub joelhooks/rat-stack. Revert; used for the production rollback. Accessed 2026-10-01.

3. [fix(mischief): isolate rate-limit stages from runtime init · joelhooks/rat-stack@6e85432 · GitHub](https://github.com/joelhooks/rat-stack/commit/6e85432034400df8e49a9354a4cab1246d7cece0)
   GitHub joelhooks/rat-stack. Runtime guard fix; used for separating declarations from isolate startup. Accessed 2026-10-01.

4. [rat-stack/apps/site/test/worker-runtime-init.test.ts at main · joelhooks/rat-stack · GitHub](https://github.com/joelhooks/rat-stack/blob/main/apps/site/test/worker-runtime-init.test.ts)
   GitHub joelhooks/rat-stack. Runtime initialization test; used to reproduce missing deploy-time services. Accessed 2026-10-01.

## Lore on this page

- [Workers answer requests; Durable Objects own named state](/lore/workers-answer-requests-durable-objects-own-named-state)
- [Bindings](/lore/bindings)

## Linked from

- Agent guide → An Effect stack so pure (aspirational) Kit Langton will blush. → [Read page](https://ratstack.sh/llms.txt)

- Change log → What changed in the files served here, newest first. → [Read page](https://ratstack.sh/log)

- Full agent guide → An Effect stack so pure (aspirational) Kit Langton will blush. → [Read page](https://ratstack.sh/llms-full.txt)

- Purpose and boundaries of rat-stack (VISION.md) → What this starter is for and what a useful copy should keep. → [Read page](https://ratstack.sh/VISION.md)

- Rat Stack lore | rat-stack → Short, source-grounded notes on the ideas and decisions behind rat-stack. → [Read page](https://ratstack.sh/lore)

- Shared caches hold completed values → Keep pending request I/O out of isolate-scoped caches. → [Read page](https://ratstack.sh/lore/cache-completed-values)

- Source change history (log.md) → The generated change log as Markdown. → [Read page](https://ratstack.sh/log.md)

- There is no ISR on Cloudflare → SvelteKit's Vercel ISR setting does not configure Workers Cache; our local comparison did not prove cache reuse. → [Read page](https://ratstack.sh/lore/there-is-no-isr-on-cloudflare)

- Workers answer requests; Durable Objects own named state → A Worker must not rely on module state between requests, so state that must persist lives in a Durable Object addressed by name. → [Read page](https://ratstack.sh/lore/workers-answer-requests-durable-objects-own-named-state)
