Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Prelude vs Layer

The prelude and layer fields in WorkerdActorRuntime.make(...) serve different lifetimes.

Use prelude for long-lived infrastructure:

  • database access
  • config
  • logging
  • asset bindings
  • Cloudflare service bindings

Use layer for short-lived context derived from the current client-specific actor invocation:

  • current user id
  • current authorization

Derive request context

The next example builds a layer that provides an actor-specific CurrentUserId derived from two different actor definitions.

import { Context, Effect, Layer, Schema as S } from "effect"
 
import { ChatActor } from "../chat/ChatActor.ts"
import { LobbyActor } from "../lobby/LobbyActor.ts"
 
const UserId = S.String.pipe(S.brand("UserId"))
 
export class CurrentUserId extends Context.Service<CurrentUserId, typeof UserId.Type>()("CurrentUserId") {}
 
// Use the actor name as the id.
export const layerLobby = Effect.gen(function* () {
  const { name } = yield* LobbyActor
  return name
}).pipe(Layer.effect(CurrentUserId))
 
// Use the current client attachment as the id.
export const layerChat = Effect.gen(function* () {
  const { currentClient } = yield* ChatActor
  const { userId } = yield* currentClient.attachments
  return userId
}).pipe(Layer.effect(CurrentUserId))

In Effect v4, context is defined with Context.Service<Self, A>()(id). This replaces Context.Tag from earlier versions.

Read Actor Context for the values available through yield* ActorTag.