Effect basics
A service is a named interface for work. A context holds supplied service implementations.¶
An Effect describes work. Build the description, compose it with other Effects, supply its services, then let a runtime execute it.¶
Read the three type parameters
Effect.Effect<A, E, R> describes three things:¶
This method’s full return type is Effect.Effect<FileStats, FileStatsError, never>.
The source omits the final parameter because it defaults to never.¶
export class FileInspector extends Context.Service<
FileInspector,
{
readonly inspect: (
path: string
) => Effect.Effect<FileStats, FileStatsError>;
}
>()("@rat-stack/core/FileInspector", {
make: Effect.gen(function* makeFileInspector() {
const fileSystem = yield* FileSystem.FileSystem;Constructing the inspector needs FileSystem. Its returned method has captured that dependency and does not require it again.¶
R = never means no services remain to supply. It does not mean the computation cannot fail. E = never means no declared expected failures; it does not rule out defects or interruption.¶
A description is not a completed operation
Calling inspector.inspect(path) produces an Effect description. It does not read the file immediately.
The method composes the read with an error translation before a runtime executes either operation.¶
const inspect = Effect.fn("FileInspector.inspect")(function* inspect(
path: string
) {
const content = yield* fileSystem
.readFile(path)
.pipe(
Effect.mapError(
(error) => new FileStatsError({ path, reason: error.message })
)
);
return summarizeBytes(path, content);
});Ordinary JavaScript still evaluates while you build a description. Starting a Promise first, then wrapping it, does not undo that eager work. Keep external work inside the Effect constructor’s callback.¶
Write a sequence with gen; transform it with pipe
Effect.gen composes Effects in generator syntax. yield* obtains a success value or propagates the failure.
The generator describes work for the Effect runtime.¶
Use pipe for short transforms, such as mapping a value, translating a failure, or providing a service.
Use a generator when the next step needs values from earlier steps.¶
- Combinators are functions that combine or transform Effects.¶
Generators and combinators both compose descriptions without running a nested runtime.¶
- In rat-stack, prefer
Effect.genfor inline sequences. UseEffect.fnfor reusable functions with useful tracing names.¶ - Do not write long combinator chains merely to avoid a clear generator.¶
Expected failures and defects are different
An expected failure39 belongs in E, where callers can handle it by its declared type or tag.
A defect is an unexpected execution failure.
Logging a failure does not make the operation successful. Handle expected failures without hiding defects39 shows the file error and its CLI handler.¶
Requirements name services to supply
A requirement is a service the computation needs. A Layer describes how to build a service and supply its dependencies.¶
Layers build implementations and satisfy their construction dependencies.
Getting FileInspector from context requires that service; calling its captured inspect method needs no extra service.
Read service construction26, Layer composition18, and context and requirements9.¶
Run at the application boundary
The CLI builds and transforms a program with pipe, then provides its services and their dependencies. NodeRuntime.runMain executes the final Effect:¶
Effect.provide(
Layer.mergeAll(
Layer.provideMerge(FileInspector.layer, NodeServices.layer),
remoteJoinInterestLayer,
localPromptLibraryLayer.pipe(Layer.provide(NodeServices.layer)),
localCafeDirectoryLayer.pipe(Layer.provide(NodeServices.layer)),
localLearnLayer,
Flags.defaults(eventFlags),
Approval.denyAll
)
)
);
NodeRuntime.runMain(program);The Worker returns a fetch Effect to its Alchemy Worker adapter:¶
return {
fetch: observeRequestLog(
observeRequestIncidents(
events === undefined
? readerApp
: Effect.gen(function* captureWithLiveIdentity() {
return yield* withEventCapture({
captureCity: true,
identityMode: currentIdentity,
runInBackground: inBackground,
})(readerApp).pipe(Effect.provideContext(events));
})
)
),
};The Worker adapter owns request execution. The domain does not scatter runPromise calls through handlers.¶
In tests, it.effect owns execution of the returned Effect. The test still supplies the services it needs.
See tests through supplied services22. Run Effect at the integration boundary8 covers foreign code, runtime reuse, and disposal.¶
The common wrong first version
Scattering await Effect.runPromise(...) through library methods creates separate execution boundaries where composition should remain intact.
It also turns the expected failure into a rejected Promise rather than preserving the Effect error channel for the caller.
Return the composed Effect and let the application boundary run it.¶
Effect.promise assumes Promise rejection is an unexpected defect.
For an external API with expected failures, use Effect.tryPromise with a translation into a named domain error10.
Wrapping an already-started Promise also loses control over when its work begins.¶
Read next
- Effect basics: build a description before running it.¶
- Schemas define the boundary25: define and decode accepted data.¶
- Expected failures and defects39: name failures without hiding crashes.¶
- Service construction26: capture implementation dependencies.¶
- Layer composition18: supply the graph at an entrypoint.¶
- Configuration7: parse supplied settings.¶
- Testing22: prove behavior through supplied services.¶
- Scopes34: acquire resources inside their owner and release them on exit.¶
- Concurrency23: bound work and stop owned children.¶
- HTTP responses9: check status and decode accepted data.¶
- Tracing7: name meaningful operations and inspect export evidence.¶
- Runtime boundaries8: execute through the framework’s Effect integration and connect disposal.¶
Sources
- Arnaldi, Michael. n.d. TypeScript & Effects with Michael Arnaldi. Happy Path 81.. Michael Arnaldi. Historical explanation at 49:15 of success, errors, and requirements; current API evidence comes from the pinned source. Accessed 2026-10-06.
- Arnaldi, Michael. n.d. Why JavaScript Is Broken: How Effect and TypeScript Fixes It.. Michael Arnaldi. Historical explanation at 12:32 of lazy computations that can be transformed before execution. Accessed 2026-10-06.
- Effect contributors. 2026. Effect. Effect 4.0.0.. Effect-TS. Effect<A, E, R>, lazy execution, gen, mapError, fn, and typed failure handling. Accessed 2026-10-06.
- Effect contributors. 2026. Context. Effect 4.0.0.. Effect-TS. Service keys express requirements; supplied context satisfies them. Accessed 2026-10-06.
- Effect contributors. 2026. Effect Vitest integration.. Effect-TS. it.effect owns execution of an Effect returned by a test. Accessed 2026-10-06.
- rat-stack contributors. 2026. rat-stack source snapshot.. rat-stack. FileInspector's method type, CLI composition and execution, Worker fetch Effect, and Effect-aware tests. Accessed 2026-10-06.
Last changed 2026-10-24 in c525d23. Source on GitHub. Change log.
Linked from
- Accumulate independent errors before writing output. Check every independent job before any job writes an asset.
Effect 4’s Effect.validate evaluates every collection element.
- Agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
Effect basics — An Effect describes work, expected failures, and required services before a runtime executes it.
- CAFE all stars. Public profiles of people and channels who build with Cloudflare, Alchemy, Foldkit and Effect, served by five read-only capabilities.
CAFE all stars lists people and channels whose public work builds with Cloudflare, Alchemy, Foldkit and Effect.
- Change log. What changed in the files served here, newest first.
Effect basics — edited: fix(site): replace published Markdown tables with lists and fence reader output
- Cleanup can be an idempotent postcondition. Already-absent state can be success when absence is the operation’s intended result.
Put the domain meaning in the service contract; Effect supplies execution.
- Concurrent work needs an owner and a bound. Limit active work, retain result order, and stop child work when its owning lifetime ends.
Return to the Effect reading order.¶
- Context and requirements. Effect requirements make a computation's needed services visible in its type.
See Effect basics and infrastructure as effects.¶
- durability. Keep a rat-stack app standing when a provider, pool, or dependency slows down or a worker dies. Use at any I/O boundary, connection pool, provider call, shared waiter, fan-out, flag, gate, or work that can outlive a request, or when asked "what happens when this is slow", "add a timeout", "make this durable", or "what survives a crash".
Effect runs each fiber as a concurrent computation in one JavaScript runtime, not as an isolated process.
- Durability. Seven durable Effect patterns, each with its seam, its fence, and the incident that taught it.
rat-stack uses Effect’s own primitives for each one, in real seams.
- Durability bibliography. Books, checked short quotations, source limits, and Effect mapping provenance.
Book principles and our Effect mappings are separate.
- Effect is not BEAM. Fibers share a runtime; scope ownership does not supply isolated heaps or OTP restart strategies.
Test a worker defect and a hard runtime exit separately.
- Effect keeps the surfaces on one contract. Schema owns values, projections build interfaces, and Layers supply implementations.
Start with Effect basics, then construct a service and compose its Layers.¶
- Failures keep their meaning. Expected refusals, infrastructure faults, and defects need different policies.
Classification and defect policy remain domain decisions.
- Feature flags. Typed feature flags with owners, removal dates, and stable subject rollouts.
Declared Effect actors record lifecycle transitions.
- Full agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
- Handle expected failures without hiding defects. Declare expected failures, preserve their context, and recover by tag without turning crashes into successful outcomes.
Such a field does not itself turn an expected error into a runtime defect.¶
- HTTP success needs a status check and a decoder. Supply the client, check the response status, decode accepted data, and name failures at the adapter boundary.
Return to the Effect reading order.¶
- learn-rat-stack. Trace a capability through Effect, XState, five projections, the CLI, and Alchemy. Try hosted search and read.
Read Effect basics before this trace if the computation model is new.
- onboard-a-list. Analyze or migrate an email list. Measure sanitation rules, preserve stops, choose a cohort, and verify an authorized import or sending cutover.
Decode policy data with Effect Schema.
- Pure cores reduce timeline coupling. Move deterministic rules out of time-dependent actions and shared mutable state.
Wrapping a callback in Effect does not make it pure.¶
- Rat Stack lore | rat-stack. Short, source-grounded notes on the ideas and decisions behind rat-stack.
Effect basics — An Effect describes work, expected failures, and required services before a runtime executes it.
- Recovery needs model tests. Test sequences of failures and recoveries against explicit invariants.
Check the model by injecting a defect.¶
- Replay needs stable inputs. Historical processing must not silently depend on today’s clock or external decisions.
Activity can record an effect result under an engine.
- Retry needs idempotent effects. Repeating an operation must preserve its intended observable result.
Processing guarantees inside one store do not cover every external side effect.¶
- Run Effect at the integration boundary. Build the runtime where a calling framework enters, reuse its services, and dispose it when that integration ends.
The basics page shows CLI, Worker and test execution boundaries.
- Scopes release resources when work ends. Acquire resources lazily, keep their use inside the owner, and release them after success, failure, or interruption.
Return to the Effect reading order.¶
- Source change history (log.md). The generated change log as Markdown.
Effect basics — edited: fix(site): replace published Markdown tables with lists and fence reader output
- Structure an Effect codebase by domain. Start with folders for application work, services and Layers in the same file, and startup code that supplies implementations.
Start with Effect basics.¶
- Trace operations where they mean something. Name useful operations, add safe context, and distinguish creating a span from delivering it to a backend.
Return to the Effect reading order.¶
Unlinked mentions (72)
- A service captures its construction dependencies → make describes service construction as an Effect.
- add-a-capability → Effect describes work with typed failures and required dependencies.
- add-a-lifecycle-machine → Effect describes work with typed failures and required dependencies.
- add-a-store → Effect describes work with typed failures and required dependencies.
- Agent rules for rat-stack (AGENTS.md) → Effect 4.0.7 and @effect/platform-node 4.0.7.
- Agents explore, tests remember → The resulting checks use Effect tests.¶
- Analytics → Effect is the library that describes work with typed failures and required services.
- Build and run rat-stack (README.md) → Build an Effect app and its cloud as one typed program.
- CAFE names the Cloudflare, Alchemy, Foldkit and Effect stack → Job: Draws the UI with the Elm Architecture on Effect.¶
- Capabilities → Effect is a library for describing work with typed failures and required services.
- CascadiaJS 2026: It's time to rethink everything → Theo compares the cloud’s effect on infrastructure with agents’ effect on software production.
- Code snippets quote a pinned source → Effect 4 exposes Arbitrary.schema through effect/Arbitrary.
- Concurrent work needs an owner and a bound → forEach describes one Effect per input and collects results in input order.
- Configuration is a supplied, validated dependency → Effect’s Config.schema can describe more complex validated settings.
- Context and requirements → Sam describes this requirements channel as a way to model permissions before execution, which he calls a static effect.
- Database → Effect describes work with typed failures and required services.
- Dependency injection is the reason to choose Effect → Dillon Mulroy compares Effect with Spring and NestJS:¶
- Dependency vendoring rules (vendor/README.md) → Effect 4.0.3 made Crypto.randomUUIDv4 a function, so the published .pipe call throws and the relay never starts.
- Devtools → Effect describes work with typed failures and required services.
- durability → Effect is not BEAM.
- Durability → Effect stays at the pinned version.
- Durability bibliography → Effect contributors.
- Durability starts with a recovery record → Effect is not BEAM.
- Effect + Alchemy peer patterns → At that study date, only alchemy-run/alchemy at 9802260db8f8b5a083c4b85eb7ea31ae1ff8f176 matched both Effect and Alchemy lines: its package is beta.79 and its workspace requires Effect rc.117.
- Effect + Alchemy peers → Effect: 4.0.7
- Effect 4 study: September 2026 → Effect: 4.0.0-rc.115 (catalog)
- Effect Days 2025: Building Effect 4 → Michael describes Effect 4 as a review of choices made in Effect 3, driven by production feedback.
- Effect keeps the surfaces on one contract → Effect Schema owns inputs, outputs, and failures in our shared contract.
- Effect Meetup SF 2023: Why Effect? → A Remix demo contrasts manually added logs, metrics, and traces and nested error handling with Effect context, Schema, spans, metrics, and retry policies.
- Effect's design lineage → John De Goes describes Effect as adapting ZIO’s goals to TypeScript through iterations rather than copying it directly.
- Fence → Effect describes work with typed failures and required services.
- find-peers → Effect describes work with typed failures and required dependencies.
- gardener → Effect describes work with typed failures and required dependencies.
- Handle expected failures without hiding defects → A defect is an unexpected execution failure.¶
- Happy Path 116: Infrastructure as effects → Effect gives Alchemy a pure program: it describes work before execution and can be planned first.
- Happy Path 81: TypeScript and effects → He describes an Effect by its output, predictable failures, and requirements.
- Hexagonal architecture → On the driven side, where the application calls services, Effect Context.Service definitions provide ports for sending interest mail, subscriber intake (SubscriberIntake), and confirmation (SubscriberConfirm).
- HTTP success needs a status check and a decoder → Effect also has native schedules and retry operators.¶
- Infrastructure as effects → A client operation can imply a policy requirement supplied when the function is built.
- investigate-a-failure → Output that looks corrupted may be a side effect of a crash.¶
- keep-or-cut → Effect describes work with typed failures and required dependencies.¶
- Learn mode presents concepts at useful depths → Effect describes the work with typed failures and required services.
- learn-alchemy → limit({ key }) method and turns a failed runtime call into a defect instead of failing open.¶
- learn-rat-stack → Effect describes work with typed failures and required dependencies.¶
- Lifecycles are machines → A side effect is work outside the state description, such as reading a file.
- Lint and type escape ledger (debt.md) → Reason: Expected failures travel in Exit output; an unexpected machine failure is a defect.
- mdsvex left unified → The fence does not permit rewriting valid prose around a parser defect.¶
- Michael Arnaldi → He describes Effect computations through their outputs, predictable failures, and requirements: the services the work needs.
- Model-based testing → Effect 4’s Arbitrary.array generates command sequences.
- One capability, every surface → Effect Schema provides types and runtime checks for these values.
- One schema, three surfaces → Effect Schema supplies types and runtime checks for these values.¶
- OpenAPI describes the refusal too → Effect’s OpenApi.fromApi derives the document from that HttpApi.¶
- Oxlint rule limits → Residual limit and why: Arbitrary helper functions, complex control flow, and Effect values whose resource ownership is hidden behind other abstractions need semantic analysis.
- profile-a-worker → One change and its measured effect, or the reason no change is worth it.¶
- Property-based testing → Effect 4 ships its own engine in effect/Arbitrary.
- Purpose and boundaries of rat-stack (VISION.md) → Effect owns the hard parts, Alchemy infers the infrastructure from the code, and the fence raises the floor, so an agent can build it reliably with high-trust.
- Rat King binds agents into one encrypted network → Effect owns contracts, services, and typed failures.¶
- rat-stack → An Effect stack so pure (aspirational) Kit Langton will blush.
- Retry needs idempotent effects → Receiver-side keys or transactional dedupe must enforce the repeated effect’s semantics.¶
- Run Effect at the integration boundary → Effect-native HTTP router: Adapt its Layer with HttpRouter.toWebHandler¶
- Schema projections: 2026-09-18 history → This study records the proposal and implementation on 2026-09-18 against Effect rc.115.
- Scopes release resources when work ends → The migration adapter makes shutdown failure a defect with orDie.
- ship → Effect: the library for describing work with typed failures and required services.¶
- Structure an Effect codebase by domain → runMain runs the final Effect.
- test-behaviour → prop when the check returns an Effect.¶
- Tests prove behavior through supplied services → effect runs the Effect returned by the test.
- The fence → Effect language-service diagnostics run through TypeScript.
- Trace operations where they mean something → Use annotateSpans when supplying annotations through an enclosing Effect.
- UI behaviour is a scene → A Command is a named side effect.
- uncomplect → Effect: The library for describing work with typed failures and required services.¶
- Vibe engineering Effect apps → Effect is a TypeScript library for describing work with typed results, failures, and required services.¶
- Worker init runs twice → A Cloudflare Worker’s initialization effect runs twice.