Layer composition makes dependencies explicit
A service is a named interface. A Layer describes how to build a service from other services. Choose and supply the services and their dependencies before running the application. Keep dependencies private unless callers need them too.¶
Supply dependencies without changing the domain
FileInspector.layer needs a filesystem implementation. NodeServices.layer supplies platform services. The CLI combines them before execution.¶
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);Choose the combinator by the services the resulting Layer should expose:¶
Layer.provide(dependency): The consuming Layer’s services¶Layer.provideMerge(dependency): The consuming Layer’s services and the dependency’s services¶Layer.mergeormergeAll: The combined services; unrelated requirements remain unresolved¶
Merging services does not, by itself, feed one Layer into another Layer’s requirements.¶
The test suite retains platform services with provideMerge because tests also create temporary files.
Production callers that need only the inspector can keep its implementation dependency private with provide.¶
Reuse Layer identity when sharing construction
Sharing follows Layer identity within a build context that remembers which Layer values it has already constructed. Equivalent construction code does not make two Layer values identical. Sharing is limited to that construction context.¶
The fixture gives two consumers a resource. One case shares a Layer value; the other calls the Layer factory again.¶
const resource = Resource.layer();
const graph = Layer.merge(
ReadAccess.layer.pipe(Layer.provide(resource)),
WriteAccess.layer.pipe(
Layer.provide(shared ? resource : Resource.layer())
)
);Resource.layer() creates a new Layer value. Reusing resource lets the two branches share construction.¶
The fixture counts constructions and compares service ids:¶
const ids = yield* Effect.gen(function* readServiceIds() {
return [yield* ReadAccess, yield* WriteAccess];
}).pipe(Effect.provide(graph));
const count = yield* ConstructionCount;
expect(yield* Ref.get(count)).toBe(constructions);
expect(ids[0] === ids[1]).toBe(shared);Independent application runtimes do not share instances merely because they import the same Layer value. Their construction context and memo-map lifetime matter too.¶
Common wrong approach
Calling a Layer factory twice can create two pools, caches, or background workers when one shared instance was intended. Keep the constructed Layer value and provide that same value to both consumers.¶
Do not use provideMerge everywhere to silence missing-service errors.
Read which services callers need. Retaining every dependency exposes implementation details and makes removal harder.¶
Effect idiom and house rule
- Layers carry output services, construction failures, and input requirements. Composition resolves the requirements.¶
- In rat-stack, each entrypoint, where the application starts, chooses and supplies implementations in its composition root17.¶
- A cartridge38 packages one job and its infrastructure. It must be removable without breaking unrelated packages.¶
- The application chooses its workspace layout and adapter package boundaries.¶
See also: service construction26, domain structure17, cartridges38, and testing22.¶
Read why dependency injection matters14.¶
Sources
- Effect contributors. 2026. Layer. Effect 4.0.0.. Effect-TS. provide supplies dependencies; provideMerge retains their services; memoization uses Layer identity and a MemoMap. Accessed 2026-10-06.
- Effect contributors. 2026. Layer tests.. Effect-TS. Tests establish shared construction and resource lifetime within memoization contexts. Accessed 2026-10-06.
- rat-stack contributors. 2026. CLI composition root.. rat-stack. The CLI provides FileInspector and platform services before NodeRuntime.runMain. Accessed 2026-10-06.
- rat-stack contributors. 2026. Layer identity fixture.. rat-stack. A checked seam fixture counts one construction for shared identity and two for separate Layer instances. Accessed 2026-10-06.
- Langton, Kit. 2026. Services & Layers. Effect Solutions.. Kit Langton. Topic framing for provision and identity-based Layer sharing; rewritten around rat-stack's code. Accessed 2026-10-06.
Last changed 2026-10-24 in c525d23. Source on GitHub. Change log.
Linked from
- A service captures its construction dependencies. Build a service with its dependencies, then expose methods that callers can use without rebuilding the graph.
Supply its Layer at the composition root, the startup code that chooses and supplies implementations.¶
- Agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
Layer composition makes dependencies explicit — Supply a service’s dependencies, choose which services remain visible, and reuse Layer identity within a build.
- Change log. What changed in the files served here, newest first.
Layer composition makes dependencies explicit — edited: fix(site): replace published Markdown tables with lists and fence reader output
- Configuration is a supplied, validated dependency. Parse configuration when a Layer builds, reject invalid values, and supply controlled settings in tests.
See also: services, Layer composition, failures, and tests.¶
- Dependency injection is the reason to choose Effect. Effect tracks service requirements in types and supplies replaceable implementations through Layers.
Read explicit Layer composition.¶
- Durability. Seven durable Effect patterns, each with its seam, its fence, and the incident that taught it.
Reference with a default, read at layer build, then Effect.timeoutOption.¶
- Durability starts with a recovery record. A reading order for storage, replay, worker ownership, overload, and recovery tests.
Layers make dependencies explicit.¶
- Effect basics. An Effect describes work, expected failures, and required services before a runtime executes it.
Read service construction, Layer composition, and context and requirements.¶
- 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.¶
- Feature flags. Typed feature flags with owners, removal dates, and stable subject rollouts.
The operator layer adds the ledger DO and its KV write binding.¶
- Full agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
- learn-rat-stack. Trace a capability through Effect, XState, five projections, the CLI, and Alchemy. Try hosted search and read.
For implementation tasks, use services, Layer composition, and testing.¶
- Pure cores reduce timeline coupling. Move deterministic rules out of time-dependent actions and shared mutable state.
Connect this to the existing rat-stack guidance.¶
- query-design. Design or review SQL reads, writes, scans, backfills, and slow database paths. Use before changing a store method or any loop that queries. Covers round-trip arithmetic, batching, keyset paging, index evidence, row budgets, PlanetScale Vitess limits, Hyperdrive connections, statement-count tests, and statement-template fences.
A Layer builds services and supplies their construction dependencies.
- Rat Stack lore | rat-stack. Short, source-grounded notes on the ideas and decisions behind rat-stack.
Layer composition makes dependencies explicit — Supply a service’s dependencies, choose which services remain visible, and reuse Layer identity within a build.
- Scopes release resources when work ends. Acquire resources lazily, keep their use inside the owner, and release them after success, failure, or interruption.
Start with Layer composition when choosing the resource’s owner.
- Source change history (log.md). The generated change log as Markdown.
Layer composition makes dependencies explicit — 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.
See Layer composition.¶
Unlinked mentions (37)
- A clean playground → A Layer describes how to build services and supply their dependencies.
- A Layer as constructor → A Layer describes how to build a service and supply its dependencies.
- A service captures its construction dependencies → A Layer describes how to build a service and supply its dependencies.
- add-a-capability → A Layer builds services and supplies their construction dependencies.¶
- add-a-lifecycle-machine → Provide its service Layer in apps/cli/src/cli.ts.
- add-a-store → A Layer builds services and supplies their construction dependencies.
- Agent rules for rat-stack (AGENTS.md) → Role: Private crash-trace archive: trace schemas, captureCrashes, and the R2 archive layer (@rat-stack/crash/r2).
- Cartridges → A Layer describes how to build services and supply their dependencies.¶
- Code snippets quote a pinned source → A Layer describes how to build a service and supply its dependencies.
- Configuration is a supplied, validated dependency → A Layer describes how to build it and supply its dependencies.
- Dependency injection is the reason to choose Effect → A Layer builds its implementation and declares its construction requirements.
- Devtools → A Layer describes how to build services and supply their construction dependencies.
- Effect + Alchemy peer patterns → This is the closest inspected resource graph to rat-stack’s planned PlanetScale Postgres Layer.
- Effect 4 study: September 2026 → Why it matters to us: Our infra layer.
- Effect basics → A Layer describes how to build a service and supply its dependencies.¶
- Effect keeps the surfaces on one contract → provide supplies a Layer’s dependencies.
- Effect Office Hours 27: Alchemy, infrastructure as effects → A Layer describes how to build services and supply their dependencies.
- Hexagonal architecture → Rat-stack’s Effect layer follows the inside/outside boundary.
- Infrastructure as effects → An Alchemy Layer can declare the cloud resources behind a service.
- investigate-a-failure → Write it down with its evidence and move to the next layer.¶
- keep-or-cut → A Layer builds services and supplies their construction dependencies.
- learn-alchemy → A Layer builds services and supplies their construction dependencies.
- learn-rat-stack → A Layer builds services and supplies their construction dependencies.¶
- Lint and type escape ledger (debt.md) → Reason: Alchemy intentionally erases exporter layer requirements in its per-event registry.
- One schema, three surfaces → ts derives HttpApi endpoints, the handler Layer, and OpenAPI.¶
- Purpose and boundaries of rat-stack (VISION.md) → With Alchemy, an Effect Layer can declare the cloud resources it needs.
- query-design → effect and a counting executor Layer at the adapter boundary.
- rat-stack → An Alchemy Layer also carries its cloud resources.
- Run Effect at the integration boundary → A Layer describes how to build a service and supply its dependencies.
- Schema projections: 2026-09-18 history → live with the layer provided inline.
- Scopes release resources when work ends → A service Layer can own that resource for its build lifetime.
- Structure an Effect codebase by domain → A Layer describes how to build a service and supply its dependencies.¶
- test-behaviour → Keep one, and supply services through a Layer:¶
- Tests prove behavior through supplied services → A Layer describes how to build a service and supply its dependencies.
- Trace operations where they mean something → Mischief and RpcBackend register a per-event telemetry Layer.
- uncomplect → Layer: A description of how to construct services and supply their dependencies.¶
- Worker init runs twice → See cartridges for the rule that each resource belongs to its Layer and the fence for the required tests that check this separation.¶