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,
Approval.denyAll
)
)
);
NodeRuntime.runMain(program);Choose the combinator by the services the resulting Layer should expose:¶
| Combinator | What the resulting Layer exposes |
|---|---|
Layer.provide(dependency) | The consuming Layer’s services |
Layer.provideMerge(dependency) | The consuming Layer’s services and the dependency’s services |
Layer.merge or mergeAll | 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 root16.¶
- A cartridge36 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 construction16, domain structure16, cartridges36, 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-07 in e73c9d9. 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: feat(learn): teach the next twenty cards with plain lines, diagrams and snippets
- 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.¶
- 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.¶
- 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.¶
- 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: feat(learn): teach the next twenty cards with plain lines, diagrams and snippets
- 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 (35)
- 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) → Devtools are capabilities: devtools(capabilities) adds the rat_* capabilities, and a dev composition provides the recording layer from devtoolsLayer() through CallWatch (@rat-stack/capability/call-watch).
- 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 → No service or layer in the example.
- 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.¶
- 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.
- 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 → ts and the provider Layer in packages/database/src/d1.ts.
- 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.¶