# Effect library documentation

This documentation resides in the Effect monorepo, which contains the source
code for the Effect library and its related packages.

When you need to find any information about the Effect library, only use this
documentation and the source code found in `./packages`. Do not use
`node_modules` or any other external documentation, as it may be outdated or
incorrect.

**Note**: The examples in this documentation contain comments for illustration
purposes. In practice, you would not include these comments in your code.

## Writing `Effect` code

Prefer writing Effect code with `Effect.gen` & `Effect.fn("name")`. Then attach
additional behaviour with combinators. This style is more readable and easier to
maintain than using combinators alone.

### Using Effect.gen

Use `Effect.gen` to write code in an imperative style similar to async await.
You can use `yield*` to access the result of an effect.

```ts
import { Effect, Schema } from "effect"

Effect.gen(function*() {
  yield* Effect.log("Starting the file processing...")
  yield* Effect.log("Reading file...")

  // Always return when raising an error, to ensure typescript understands that
  // the function will not continue executing.
  return yield* new FileProcessingError({ message: "Failed to read the file" })
}).pipe(
  // Add additional functionality with .pipe
  Effect.catch((error) => Effect.logError(`An error occurred: ${error}`)),
  Effect.withSpan("fileProcessing", {
    attributes: {
      method: "Effect.gen"
    }
  })
)

// Use Schema.TaggedErrorClass to define a custom error
export class FileProcessingError extends Schema.TaggedErrorClass<FileProcessingError>()("FileProcessingError", {
  message: Schema.String
}) {}
```

### Using Effect.fn

When writing functions that return an Effect, use `Effect.fn` to use the
generator syntax.

**Avoid creating functions that return an Effect.gen**, use `Effect.fn`
instead.

```ts
import { Effect, Schema } from "effect"

// Pass a string to Effect.fn, which will improve stack traces and also
// attach a tracing span (using Effect.withSpan behind the scenes).
//
// The name string should match the function name.
//
export const effectFunction = Effect.fn("effectFunction")(
  // You can use `Effect.fn.Return` to specify the return type of the function.
  // It accepts the same type parameters as `Effect.Effect`.
  function*(n: number): Effect.fn.Return<string, SomeError> {
    yield* Effect.logInfo("Received number:", n)

    // Always return when raising an error, to ensure typescript understands that
    // the function will not continue executing.
    return yield* new SomeError({ message: "Failed to read the file" })
  },
  // Add additional functionality by passing in additional arguments.
  // **Do not** use .pipe with Effect.fn
  Effect.catch((error) => Effect.logError(`An error occurred: ${error}`)),
  Effect.annotateLogs({
    method: "effectFunction"
  })
)

// Use Schema.TaggedErrorClass to define a custom error
export class SomeError extends Schema.TaggedErrorClass<SomeError>()("SomeError", {
  message: Schema.String
}) {}
```

### More examples

- **[Creating effects from common sources](./ai-docs/src/01_effect/01_basics/10_creating-effects.ts)**:
  Learn how to create effects from various sources, including plain values,
  synchronous code, Promise APIs, optional values, and callback-based APIs.

## Defining schemas and domain models

All validation and domain modeling in Effect is done with `Schema`.

**AVOID using predicates or manual parsing**, instead use `Schema` to parse untrusted data and validate it.

For a comprehensive guide, see [packages/effect/SCHEMA.md](./packages/effect/SCHEMA.md). Make sure to read the guide in chunks, as it is a large document.

- **[Schema basics](./ai-docs/src/01_effect/02_schema/10_schema-basics.ts)**:
  Define `Schema.Class`s, decode unknown input into typed values, and
  encode typed values back into their external representation.

## Writing Effect services

Effect services are the most common way to structure Effect code. Prefer using
services to encapsulate behaviour over other approaches, as it ensures that your
code is modular, testable, and maintainable.

### Context.Service

The default way to define a service is to extend `Context.Service`,
passing in the service interface as a type parameter.

```ts
// file: src/db/Database.ts
import { Context, Effect, Layer, Schema } from "effect"

// Pass in the service class name as the first type parameter, and the service
// interface as the second type parameter.
export class Database extends Context.Service<Database, {
  query(sql: string): Effect.Effect<Array<unknown>, DatabaseError>
}>()(
  // The string identifier for the service, which should include the package
  // name and the subdirectory path to the service file.
  "myapp/db/Database"
) {
  // Attach a static layer to the service, which will be used to provide an
  // implementation of the service.
  static readonly layer = Layer.effect(
    Database,
    Effect.gen(function*() {
      // Define the service methods using Effect.fn
      const query = Effect.fn("Database.query")(function*(sql: string) {
        yield* Effect.log("Executing SQL query:", sql)
        return [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }]
      })

      // Return an instance of the service using Database.of, passing in an
      // object that implements the service interface.
      return Database.of({
        query
      })
    })
  )
}

export class DatabaseError extends Schema.TaggedErrorClass<DatabaseError>()("DatabaseError", {
  cause: Schema.Defect()
}) {}

// If you ever need to access the service type, use `Database["Service"]`
export type DatabaseService = Database["Service"]
```

### More examples

- **[Context.Reference](./ai-docs/src/01_effect/03_services/10_reference.ts)**: For defining configuration values, feature flags, or any other service that has a default value.
- **[Composing services with the Layer module](./ai-docs/src/01_effect/03_services/20_layer-composition.ts)**:
  Build focused service layers, then compose them with `Layer.provide` and
  `Layer.provideMerge` based on what services you want to expose.
- **[Creating Layers from configuration and/or Effects](./ai-docs/src/01_effect/03_services/20_layer-unwrap.ts)**: Build a layer dynamically from an Effect / Config with `Layer.unwrap`.

## Error handling

### Error handling basics

Defining custom errors and handling them with Effect.catch and Effect.catchTag.

```ts
import { Effect, Schema } from "effect"

// Define custom errors using Schema.TaggedErrorClass
export class ParseError extends Schema.TaggedErrorClass<ParseError>()("ParseError", {
  input: Schema.String,
  message: Schema.String
}) {}

export class ReservedPortError extends Schema.TaggedErrorClass<ReservedPortError>()("ReservedPortError", {
  port: Schema.Number
}) {}

declare const loadPort: (input: string) => Effect.Effect<number, ParseError | ReservedPortError>

export const recovered = loadPort("80").pipe(
  // Catch multiple errors with Effect.catchTag, and return a default port number.
  Effect.catchTag(["ParseError", "ReservedPortError"], (_) => Effect.succeed(3000))
)

export const withFinalFallback = loadPort("invalid").pipe(
  // Catch a specific error with Effect.catchTag
  Effect.catchTag("ReservedPortError", (_) => Effect.succeed(3000)),
  // Catch all errors with Effect.catch
  Effect.catch((_) => Effect.succeed(3000))
)
```

### More examples

- **[Catch multiple errors with Effect.catchTags](./ai-docs/src/01_effect/04_errors/10_catch-tags.ts)**: Use `Effect.catchTags` to handle several tagged errors in one place.
- **[Creating and handling errors with reasons](./ai-docs/src/01_effect/04_errors/20_reason-errors.ts)**:
  Define a tagged error with a tagged `reason` field, then recover with
  `Effect.catchReason`, `Effect.catchReasons`, or by unwrapping the reason into
  the error channel with `Effect.unwrapReason`.

## Managing resources and `Scope`s

Learn how to safely manage resources in Effect using `Scope`s and finalizers.

- **[Acquiring resources with Effect.acquireRelease](./ai-docs/src/01_effect/05_resources/10_acquire-release.ts)**:
  Define a service that uses `Effect.acquireRelease` to manage the lifecycle of
  a resource, ensuring that it is properly cleaned up when the service is no
  longer needed.
- **[Creating Layers that run background tasks](./ai-docs/src/01_effect/05_resources/20_layer-side-effects.ts)**: Use Layer.effectDiscard to encapsulate background tasks without a service interface.
- **[Dynamic resources with LayerMap](./ai-docs/src/01_effect/05_resources/30_layer-map.ts)**:
  Use `LayerMap.Service` to dynamically build and manage resources that are
  keyed by some identifier, such as a tenant ID.

## Running Effect programs

- **[Running effects with NodeRuntime and BunRuntime](./ai-docs/src/01_effect/06_running/10_run-main.ts)**: Use `NodeRuntime.runMain` to run an Effect program as your process entrypoint.
- **[Using Layer.launch as the application entry point](./ai-docs/src/01_effect/06_running/20_layer-launch.ts)**: Use `Layer.launch` to run a long-running Effect program as your process entrypoint.

## Broadcasting messages with PubSub

Use `PubSub` when you need one producer to fan out messages to many consumers.

- **[Broadcasting domain events with PubSub](./ai-docs/src/01_effect/07_pubsub/10_pubsub.ts)**: Build an in-process event bus with `PubSub` and expose it as a service.

## Working with Streams

Effect Streams represent effectful, pull-based sequences of values over time.
They let you model finite or infinite data sources.

- **[Creating streams from common data sources](./ai-docs/src/03_stream/10_creating-streams.ts)**:
  Learn how to create streams from various data sources. Includes:
  
  - `Stream.fromIterable` for arrays and other iterables
  - `Stream.fromEffectSchedule` for polling effects
  - `Stream.paginate` for paginated APIs
  - `Stream.fromAsyncIterable` for async iterables
  - `Stream.fromEventListener` for DOM events
  - `Stream.callback` for any callback-based API
  - `NodeStream.fromReadable` for Node.js readable streams
- **[Consuming and transforming streams](./ai-docs/src/03_stream/20_consuming-streams.ts)**: How to transform and consume streams using operators like `map`, `flatMap`, `filter`, `mapEffect`, and various `run*` methods.
- **[Decoding and encoding streams](./ai-docs/src/03_stream/30_encoding.ts)**:
  Use `Stream.pipeThroughChannel` with the `Ndjson` & `Msgpack` modules to
  decode and encode streams of structured data.

## Integrating Effect into existing applications

`ManagedRuntime` bridges Effect programs with non-Effect code. Build one runtime
from your application Layer, then use it anywhere you need imperative execution,
like web handlers, framework hooks, worker queues, or legacy callback APIs.

- **[Using ManagedRuntime with Hono](./ai-docs/src/04_integration/10_managed-runtime.ts)**: Use `ManagedRuntime` to run Effect programs from external frameworks while keeping your domain logic in services and Layers.

## Batching external requests

Learn how to batch multiple requests into fewer external calls.

- **[Batching requests with RequestResolver](./ai-docs/src/05_batching/10_request-resolver.ts)**: Define request types with `Request.Class`, resolve them in batches with `RequestResolver`.

## Working with Schedules

Schedules define recurring patterns for retries, repeats and polling.

- **[Working with the Schedule module](./ai-docs/src/06_schedule/10_schedules.ts)**: Build schedules, compose them, and use them with `Effect.retry` and `Effect.repeat`.

## Working with DateTime

When working with dates and time, use the `DateTime` module instead of `Date` and `Date.now`.

Use it when your Effect programs need testable current time, safe parsing, stable ISO formatting, time-zone conversion, or calendar arithmetic.

- **[Creating and formatting DateTime values](./ai-docs/src/07_datetime/10_creating-and-formatting.ts)**:
  Parse incoming date values safely, use Clock-powered current time, and format
  instants for API payloads or user-facing labels.
- **[Working with time zones](./ai-docs/src/07_datetime/20_time-zones.ts)**:
  Attach IANA zones to instants, render zoned ISO strings, and provide a
  CurrentTimeZone service for code that should use the workspace/user zone.

## Observability

Effect has built-in support for structured logging, distributed tracing, and
metrics. For exporting telemetry, use the lightweight Otlp modules from
`effect/unstable/observability` in new projects, or use
`@effect/opentelemetry` NodeSdk when integrating with an existing OpenTelemetry
setup.

- **[Customizing logging](./ai-docs/src/08_observability/10_logging.ts)**: Configure loggers & log-level filtering for production applications.
- **[Setting up tracing with Otlp modules](./ai-docs/src/08_observability/20_otlp-tracing.ts)**: Configure Otlp tracing + log export with a reusable observability layer.

## Testing Effect programs

- **[Writing Effect tests with @effect/vitest](./ai-docs/src/09_testing/10_effect-tests.ts)**: Using `it.effect` for Effect-based tests.
- **[Testing services with shared layers](./ai-docs/src/09_testing/20_layer-tests.ts)**: How to test Effect services that depend on other services.

## Runtime type guards

The `Predicate` module contains small, reusable runtime checks.

**NEVER** write your own helper functions like `isRecord` or `isString`, instead
use the helpers from the `Predicate` module.

Predicates can be composed with apis such as `Predicate.and`,
`Predicate.or`, `Predicate.not`, and `Predicate.compose`.

### Using the Predicate module



```ts
import { Predicate } from "effect"

const thing: unknown = {
  a: 1
}

if (Predicate.isObject(thing)) {
  if (Predicate.isNumber(thing.a)) {
    console.log("number", thing.a)
  }
}
```

## Effect HttpClient

Build http clients with the `HttpClient` module.

- **[Getting started with HttpClient](./ai-docs/src/50_http-client/10_basics.ts)**: Define a service that uses the HttpClient module to fetch data from an external API

## Building HttpApi servers

`HttpApi` gives you schema-first, type-safe HTTP APIs with runtime validation, typed clients, and OpenAPI docs from one definition.

- **[Getting started with HttpApi](./ai-docs/src/51_http-server/10_basics.ts)**:
  Define a schema-first API, implement handlers, secure endpoints with
  middleware, serve it over HTTP, and call it using a generated typed client.

## Working with child processes

Use the `effect/unstable/process` modules to define child processes and run them with `ChildProcessSpawner.

- **[Working with child processes](./ai-docs/src/60_child-process/10_working-with-child-processes.ts)**: This example shows how to collect process output, compose pipelines, and stream long-running command output.

## Building CLI applications

Use the "effect/unstable/cli" modules to build CLI applications. These modules
provide utilities for parsing command-line arguments, handling user input, and
managing the flow of a CLI application.

- **[Getting started with Effect CLI modules](./ai-docs/src/70_cli/10_basics.ts)**:
  Build a command-line app with typed arguments and flags, then wire subcommand
  handlers into a single executable command.

## Working with AI modules

Effect's AI modules provide a provider-agnostic interface for language models.
You can generate text, decode structured objects with `Schema` and stream partial
responses.

- **[Using LanguageModel for text, objects, and streams](./ai-docs/src/71_ai/10_language-model.ts)**:
  Configure a provider once, then use `LanguageModel` for plain text
  generation, schema-validated object generation, and streaming responses.
- **[Defining and using AI tools](./ai-docs/src/71_ai/20_tools.ts)**:
  Define tools with schemas, group them into toolkits, implement handlers,
  and pass them to `LanguageModel.generateText`.
- **[Stateful chat sessions](./ai-docs/src/71_ai/30_chat.ts)**:
  The AI `Chat` module maintains conversation history automatically. Build
  AI agents or chat assistants.

## Building distributed applications with cluster

The cluster modules let you model stateful services as entities and distribute
them across multiple machines.

- **[Defining cluster entities](./ai-docs/src/80_cluster/10_entities.ts)**: Define distributed entity RPCs and run them in a cluster.