Shared caches hold completed values
A Worker isolate can serve several requests. A request owns its unfinished I/O. Shared caches must contain completed values.ΒΆ
The cold-isolate 1101 failure in PR #64 crossed that boundary. ContentStore held pending asset reads in a shared cache. Another request could await work owned by the first request.ΒΆ
Effect.cached, Effect.cachedWithTTL, and Effect.cachedInvalidateWithTTL can share pending work. A successful result cache and a pending-work cache have different lifetimes.ΒΆ
Store the result after the read
ContentStore keeps an Option in a Ref. Each request reads that completed-value cache first.ΒΆ
- A hit returns the completed value.ΒΆ
- A miss reads assets within the current request.ΒΆ
- A successful read stores its completed value.ΒΆ
- A failed read leaves the cache empty.ΒΆ
Concurrent misses can repeat a read. They do not wait for another requestβs unfinished read.ΒΆ
request A ββ cache miss ββ asset read ββ completed value ββ cache
request B ββ cache miss ββ asset read ββ completed value ββ cache
request C ββ cache hit ββββββββββββββββββββββββββββββββ value The cache is a derived copy of generated content assets. The content build writes those assets; requests store only successfully decoded values.ΒΆ
Check the lifetime at construction
rat-stack-patterns/no-shared-pending-cache rejects these cache constructors in module, service, and Worker initialization effects. Keep request-local work inside its request handler.ΒΆ
A targeted exception must explain the cached value and its lifetime with a -- reason. CryptoKey derivation from a fixed secret needs separate review from request-bound asset reads.ΒΆ
The fixture tests plant the old ContentStore.make cache shape. The rule rejects it before it can reach a Worker.ΒΆ
See Worker init runs twice8 for the initialization boundary and the fence39 for validation.ΒΆ
Sources
- Cache completed content without shared request I/O. GitHub joelhooks/rat-stack. ContentStore replaces shared pending asset reads with completed-value caches. Accessed 2026-10-08.
- Be explicit about lifetimes. GitHub just-be-dev. Assign each resource and mutable value to an explicit lifetime. Accessed 2026-10-08.
- Request lifetime guardrail. GitHub just-be-dev. Keep request identity and instance locks within their owning lifetimes. Accessed 2026-10-08.
Last changed 2026-10-08 in ad718e1. Source on GitHub. Change log.
Linked from
- Agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
Shared caches hold completed values β Keep pending request I/O out of isolate-scoped caches.
- Change log. What changed in the files served here, newest first.
Shared caches hold completed values β new page: feat: fence shared pending caches and teach request lifetimes
- Effect + Alchemy peer patterns. Source-grounded patterns from repos on nearby Effect and Alchemy pins.
rat-stack already adapts this guidance in cache completed values, UI tests, and opt-in tracing.
- Full agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
- profile-a-worker. Capture a CPU or heap profile of a deployed Cloudflare Worker or Durable Object and read it with pprof. Use when a Worker is slow, burns CPU, nears its memory limit, throws Exceeded Memory, or you need to know which function costs the most in production.
Link context
Common wins: compute a value once instead of per call, cache a completed value, stop building objects you throw away, remove code that a flag only half disables.ΒΆ
- Rat Stack lore | rat-stack. Short, source-grounded notes on the ideas and decisions behind rat-stack.
Shared caches hold completed values β Keep pending request I/O out of isolate-scoped caches.
- Source change history (log.md). The generated change log as Markdown.
Shared caches hold completed values β new page: feat: fence shared pending caches and teach request lifetimes