# Dependency injection is the reason to choose Effect

> For agents: start with the [agent guide](https://ratstack.sh/llms.txt). Every page is Markdown by default; add `Accept: text/html` for HTML.

Free workshop: [how to burn a trillion tokens and get good results](/tokenmaxx#interested).

Matt Pocock puts dependency injection first:

> Now, what I think people get wrong is that they think that error handling and the type-safe nature of Effect is the reason you go for Effect. I think the reason you go for Effect is dependency injection, actually. It allows you to create these beautiful small modules that you can just swap out as needed and create these really nice looking tests with Effect too.

Dillon Mulroy compares Effect with Spring and NestJS:

> Effect has probably the most novel dependency injection system that I've worked with. I've worked in enterprise languages like Java, done the whole Spring system. I've worked with NestJS. Effect's dependency injection is genuinely fantastic and really, really nice to work with.

[Watch Dillon's one-minute clip](https://player.mux.com/nB8qFbdBBHVU6zUfXsbtHFR2tKgEnjYEiPd4bL4Jny4).

## Requirements stay visible

An `Effect<A, E, R>` describes its result, failure, and required services. The `R` type tracks those requirements. The compiler rejects execution while a required service remains in `R`.

A service gives callers a typed interface. A Layer builds its implementation and declares its construction requirements. Shared Layer identity reuses construction within the same memoization context.

## A service captures its dependencies

`FileInspector.make` obtains `FileSystem` during construction. Its `inspect` method uses that captured service. The method's type carries no filesystem requirement.

packages/core/src/file-inspector.ts at c39e106e33eaa00432454ed31c59fa90389255d0; lines 6-16; highlighted none. Title: FileInspector captures FileSystem.

```typescript
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;

```

The static Layer builds the service through `make`.

packages/core/src/file-inspector.ts at c39e106e33eaa00432454ed31c59fa90389255d0; lines 17-35; highlighted none. Title: The inspection method and static Layer.

```typescript
    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);
    });

    return { inspect } as const;
  }),
}) {
  static readonly layer = Layer.effect(this, this.make);
}
```

## Tests supply another implementation

The inspection model test supplies a controlled `FileInspector`. Its fake waits for a result chosen by the test. One `provideService` replaces the implementation.

packages/core/test/inspect-machine.model.test.ts at c39e106e33eaa00432454ed31c59fa90389255d0; lines 125-135; highlighted none. Title: A controlled FileInspector.

```typescript
  const inspector = FileInspector.of({
    inspect: (path) => {
      requested.push(path);

      return Deferred.await(result);
    },
  });

  const actor = yield* createEffectActor(inspectMachine, {
    input: { path: scenario.stats.path },
  }).pipe(Effect.provideService(FileInspector, inspector));
```

`Effect.provide` supplies a Layer or Context. `Effect.provideService` supplies one service directly. Both remove the supplied service from the requirements type.

## Follow the dependency injection path

1. Read [context and requirements](/lore/context-and-requirements).
2. Read [services that capture dependencies](/lore/services-capture-dependencies).
3. Read [the Layer constructor pattern](/lore/layer-constructor-pattern).
4. Read [explicit Layer composition](/lore/layers-make-dependencies-explicit).
5. Read [configuration as a dependency](/lore/configuration-is-a-dependency).
6. Read [tests through supplied services](/lore/tests-that-earn-their-place).

## Sources

1. Matt Pocock in conversation with Joel Hooks
   Recorded 2026-10-05. Recorded conversation; quoted with permission.

2. Dillon Mulroy, recorded for Joel Hooks's AI Engineer World's Fair 2026 workshop
   Recorded 2026-06-29. Recorded workshop contribution; quoted with permission.

3. [Effect contributors. Effect 4.0.0 requirements and service provision.](https://github.com/Effect-TS/effect/blob/67ba4e46a11ccda0b6761578bfd22c04ae00167d/packages/effect/src/Effect.ts)
   Effect-TS. The R type tracks requirements; provide and provideService remove supplied requirements. Accessed 2026-10-07.

4. [Effect contributors. Effect 4.0.0 Layers.](https://github.com/Effect-TS/effect/blob/67ba4e46a11ccda0b6761578bfd22c04ae00167d/packages/effect/src/Layer.ts)
   Effect-TS. Layers construct services, compose requirements, and share construction through a MemoMap. Accessed 2026-10-07.

5. [rat-stack FileInspector.](https://github.com/joelhooks/rat-stack/blob/c39e106e33eaa00432454ed31c59fa90389255d0/packages/core/src/file-inspector.ts)
   rat-stack. The service captures FileSystem during construction and supplies a static layer. Accessed 2026-10-07.

6. [rat-stack inspection model test.](https://github.com/joelhooks/rat-stack/blob/c39e106e33eaa00432454ed31c59fa90389255d0/packages/core/test/inspect-machine.model.test.ts)
   rat-stack. The test replaces FileInspector with a controlled implementation through provideService. Accessed 2026-10-07.

## Lore on this page

- [Matt Pocock's skills](/lore/matt-pocock-skills)

## Linked from

- A Layer as constructor → Sam Goodwin compares an Effect Layer that builds a service to a constructor. → [Read page](https://ratstack.sh/lore/layer-constructor-pattern)

- A service captures its construction dependencies → Build a service with its dependencies, then expose methods that callers can use without rebuilding the graph. → [Read page](https://ratstack.sh/lore/services-capture-dependencies)

- Agent guide → An Effect stack so pure (aspirational) Kit Langton will blush. → [Read page](https://ratstack.sh/llms.txt)

- Change log → What changed in the files served here, newest first. → [Read page](https://ratstack.sh/log)

- Configuration is a supplied, validated dependency → Parse configuration when a Layer builds, reject invalid values, and supply controlled settings in tests. → [Read page](https://ratstack.sh/lore/configuration-is-a-dependency)

- Context and requirements → Effect requirements make a computation's needed services visible in its type. → [Read page](https://ratstack.sh/lore/context-and-requirements)

- Effect Days 2024: The origin story → Michael Arnaldi traces Effect to a TypeScript team's needs for tests, dependencies, and resource safety. → [Read page](https://ratstack.sh/lore/effect-days-2024-origin-story-michael-arnaldi)

- Effect's design lineage → Michael Arnaldi describes Effect's path from fintech needs through ZIO influence and TypeScript iterations. → [Read page](https://ratstack.sh/lore/effect-design-lineage)

- Full agent guide → An Effect stack so pure (aspirational) Kit Langton will blush. → [Read page](https://ratstack.sh/llms-full.txt)

- Layer composition makes dependencies explicit → Supply a service's dependencies, choose which services remain visible, and reuse Layer identity within a build. → [Read page](https://ratstack.sh/lore/layers-make-dependencies-explicit)

- Learn rat-stack from your own agent → Turn on learn mode: your own agent explains rat-stack ideas during real work and keeps progress local. → [Read page](https://ratstack.sh/learn)

- Michael Arnaldi → Michael Arnaldi develops Effect and explains its TypeScript design in public talks. → [Read page](https://ratstack.sh/lore/michael-arnaldi)

- Rat Stack lore | rat-stack → Short, source-grounded notes on the ideas and decisions behind rat-stack. → [Read page](https://ratstack.sh/lore)

- Source change history (log.md) → The generated change log as Markdown. → [Read page](https://ratstack.sh/log.md)

- Tests prove behavior through supplied services → Supply services through Layers, choose properties or models for domain rules, and reject tests that cannot detect broken behavior. → [Read page](https://ratstack.sh/lore/tests-that-earn-their-place)
