# Accessing Services

Every Effect carries a third type parameter — its **requirements** (the `R` in
`Effect<A, E, R>`). Those requirements are the services the effect needs in
order to run. This page is about the combinators that let you **read** those
services from inside Effect code and **provide** them at the edges of your
program.

This page does *not* cover how to *define* a service or build a `Layer` — that
material lives in [Services](https://effect.plants.sh/services-and-layers/services/) and
[Managing Layers](https://effect.plants.sh/services-and-layers/managing-layers/). Here we assume a
service already exists and focus on accessing it.

## The common case

Define a tiny service with `Context.Service`, read it inside `Effect.gen`, and
provide it once at the edge with `Effect.provide`.

```ts
import { Context, Effect, Layer } from "effect"

// 1. Define a service: an identifier paired with its shape. Attach a static
//    `layer` that supplies the implementation (the idiomatic v4 pattern).
class Greeter extends Context.Service<Greeter, {
  greet: (name: string) => string
}>()("Greeter") {
  static readonly layer = Layer.succeed(Greeter)({
    greet: (name) => `Hello, ${name}!`
  })
}

// 2. Read the service inside a generator.
//    `yield* Greeter` is the idiomatic way to read it — the service value
//    "flows out" of the yield, and `Greeter` is added to the requirements.
const program = Effect.gen(function*() {
  const greeter = yield* Greeter
  return greeter.greet("Effect")
})
//    program: Effect<string, never, Greeter>

// 3. Provide the implementation at the edge, discharging the requirement.
const runnable = program.pipe(Effect.provide(Greeter.layer))
//    runnable: Effect<string, never, never>

Effect.runPromise(runnable).then(console.log)
// => "Hello, Effect!"
```

The key idea: reading a service (`yield* Greeter`) *adds* it to the `R` channel;
providing it (`Effect.provide`) *removes* it. A program is runnable once `R`
has been narrowed to `never`.

```ts "Greeter" "never"
//        before provide          after provide
// Effect<string, never, Greeter> -> Effect<string, never, never>
```

## Reading from the environment

These combinators pull values out of the current context.

### Effect.service

`Effect.service(key)` returns `Effect<S, never, I>` — the explicit form of
reading a service. It adds the service to the effect's requirements.

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

class Database extends Context.Service<Database>()("Database", {
  make: Effect.succeed({
    query: (sql: string) => Effect.succeed(`rows for: ${sql}`)
  })
}) {}

const program = Effect.gen(function*() {
  const db = yield* Effect.service(Database)
  return yield* db.query("SELECT * FROM users")
})
// => Effect<string, never, Database>
```

`yield* Database` inside a generator is the idiomatic sugar for
`yield* Effect.service(Database)` — both produce the same effect. Reach for the
explicit `Effect.service` form when composing with `.pipe` outside a generator:

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

const greeting = Effect.service(Database).pipe(
  Effect.flatMap((db) => db.query("SELECT name FROM users LIMIT 1"))
)
// => Effect<string, never, Database>
```

### Effect.serviceOption

`Effect.serviceOption(key)` returns `Effect<Option<S>>` — it reads an *optional*
dependency. If the service is present you get `Option.some(impl)`; if it is
absent you get `Option.none()`. Crucially, it does **not** add the service to
the requirements, so the effect stays runnable without it.

```ts
import { Context, Effect, Option } from "effect"

class Logger extends Context.Service<Logger>()("Logger", {
  make: Effect.succeed({ log: (msg: string) => Effect.sync(() => console.log(msg)) })
}) {}

const program = Effect.gen(function*() {
  const maybeLogger = yield* Effect.serviceOption(Logger)
  if (Option.isSome(maybeLogger)) {
    yield* maybeLogger.value.log("Logger is available")
  }
  return "done"
})
// => Effect<string, never, never>   (Logger is NOT a requirement)

// Without providing Logger, the optional branch is simply skipped:
Effect.runPromise(program).then(console.log)
// => "done"
```

Use `serviceOption` for soft dependencies — telemetry, an optional cache — where
the program should degrade gracefully when the service is missing.

### Effect.context

`Effect.context()` returns `Effect<Context<R>>` — the whole context as a value.
Useful when you want to inspect, capture, or forward the entire environment.

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

class Database extends Context.Service<Database>()("Database", {
  make: Effect.succeed({ query: (sql: string) => Effect.succeed(sql) })
}) {}

const program = Effect.gen(function*() {
  const ctx = yield* Effect.context<Database>()
  // ctx is a Context<Database>; pull values out with Context.get
  const db = Context.get(ctx, Database)
  return yield* db.query("SELECT 1")
})
// => Effect<string, never, Database>
```

### Effect.contextWith

`Effect.contextWith(f)` maps over the current context, where `f` receives the
full `Context<R>` and returns an effect. Use it to branch on which services are
available before committing to a path.

```ts
import { Console, Context, Effect, Option } from "effect"

class Cache extends Context.Service<Cache>()("Cache", {
  make: Effect.succeed({ get: (key: string) => `cached:${key}` })
}) {}

const program = Effect.contextWith((ctx: Context.Context<never>) => {
  const cache = Context.getOption(ctx, Cache)
  return Option.isSome(cache)
    ? Effect.succeed(cache.value.get("user:1"))
    : Console.log("no cache").pipe(Effect.as("fallback"))
})

Effect.runPromise(program).then(console.log)
// => "fallback"   (Cache was never provided)
```

## Providing services and context

These combinators *discharge* requirements — they remove a service from the `R`
channel by supplying an implementation.

### Effect.provide

`Effect.provide(layerOrContext)` is the one you reach for most. It accepts a
`Layer` (or array of layers), or a prebuilt `Context`, and removes the services
they supply from the effect's requirements. Layers are memoized across `provide`
calls by default; pass `{ local: true }` to rebuild the layer each time.

```ts
import { Context, Effect, Layer } from "effect"

class Database extends Context.Service<Database, {
  query: (sql: string) => Effect.Effect<string>
}>()("Database") {
  static readonly layer = Layer.succeed(Database)({
    query: (sql) => Effect.succeed(`rows for: ${sql}`)
  })
}

const program = Effect.gen(function*() {
  const db = yield* Database
  return yield* db.query("SELECT * FROM users")
})
// => Effect<string, never, Database>

const runnable = program.pipe(Effect.provide(Database.layer))
// => Effect<string, never, never>

Effect.runPromise(runnable).then(console.log)
// => "rows for: SELECT * FROM users"
```

Provide several layers at once by passing an array:

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

declare const DatabaseLive: Layer.Layer<unknown>
declare const LoggerLive: Layer.Layer<unknown>
declare const program: Effect.Effect<string, never, unknown>

const runnable = program.pipe(
  Effect.provide([DatabaseLive, LoggerLive])
)
// => requirements supplied by either layer are removed
```

### Effect.provideContext

`Effect.provideContext(context)` provides an already-built `Context`, fulfilling
all the service requirements contained in it at once. Use it when you have
assembled a `Context` value directly rather than through layers.

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

class Logger extends Context.Service<Logger, {
  log: (msg: string) => void
}>()("Logger") {}
class Config extends Context.Service<Config, {
  name: string
}>()("Config") {}

// Build a context holding multiple services
const context = Context.make(Logger, { log: console.log }).pipe(
  Context.add(Config, { name: "World" })
)

const program = Effect.gen(function*() {
  const logger = yield* Logger
  const config = yield* Config
  logger.log(`Hello ${config.name}`)
})

const runnable = program.pipe(Effect.provideContext(context))
// => Effect<void, never, never>

Effect.runPromise(runnable)
// => logs "Hello World"
```

### Effect.provideService

`Effect.provideService(key, impl)` provides a single service value directly — no
`Layer` required. It removes exactly that one service from the requirements.

```ts
import { Console, Context, Effect } from "effect"

class Config extends Context.Service<Config, {
  apiUrl: string
}>()("Config") {}

const fetchData = Effect.gen(function*() {
  const config = yield* Config
  yield* Console.log(`Fetching from: ${config.apiUrl}`)
  return "data"
})

const runnable = fetchData.pipe(
  Effect.provideService(Config, { apiUrl: "https://api.example.com" })
)
// => Effect<string, never, never>

Effect.runPromise(runnable).then(console.log)
// => logs "Fetching from: https://api.example.com"
// => "data"
```

### Effect.provideServiceEffect

`Effect.provideServiceEffect(key, acquire)` provides a service whose
implementation is produced by an *effect*. The acquisition runs each time the
wrapped effect runs, and any failures in `acquire` are surfaced in the error
channel.

```ts
import { Console, Context, Effect } from "effect"

class Database extends Context.Service<Database, {
  query: (sql: string) => Effect.Effect<string>
}>()("Database") {}

// The implementation is built effectfully (e.g. opening a connection)
const createConnection = Effect.gen(function*() {
  yield* Console.log("connecting...")
  yield* Effect.sleep("10 millis")
  return { query: (sql: string) => Effect.succeed(`rows for: ${sql}`) }
})

const program = Effect.gen(function*() {
  const db = yield* Database
  return yield* db.query("SELECT 1")
})

const runnable = program.pipe(
  Effect.provideServiceEffect(Database, createConnection)
)
// => Effect<string, never, never>

Effect.runPromise(runnable).then(console.log)
// => logs "connecting..."
// => "rows for: SELECT 1"
```

For implementations that need finalization (closing the connection), prefer a
scoped `Layer` — see [Managing Layers](https://effect.plants.sh/services-and-layers/managing-layers/).

## Locally overriding services

Sometimes you want to swap a service implementation for *one* subtree of your
program without changing how it is provided at the edge — for example, raising
the log level or bumping a config value just for a critical section.

### Effect.updateService

`Effect.updateService(key, f)` transforms the implementation of an
already-present service for the wrapped effect. The service must still be
provided somewhere upstream — `updateService` keeps it in the requirements.

```ts
import { Console, Context, Effect } from "effect"

class Counter extends Context.Service<Counter, {
  count: number
}>()("Counter") {}

const program = Effect.gen(function*() {
  const counter = yield* Counter
  yield* Console.log(`count: ${counter.count}`)
  return counter.count
}).pipe(
  // bump the count just for this effect
  Effect.updateService(Counter, (c: { count: number }) => ({ count: c.count + 1 }))
)

const runnable = program.pipe(Effect.provideService(Counter, { count: 0 }))

Effect.runPromise(runnable).then(console.log)
// => logs "count: 1"
// => 1
```

A realistic use: override the logger for one noisy subtree while the rest of the
app keeps the default.

```ts
import { Console, Context, Effect } from "effect"

class Logger extends Context.Service<Logger, {
  log: (m: string) => Effect.Effect<void>
}>()("Logger") {}

const subtree = Effect.gen(function*() {
  const logger = yield* Logger
  yield* logger.log("inside the verbose section")
})

const verbose = subtree.pipe(
  Effect.updateService(Logger, (base: { log: (m: string) => Effect.Effect<void> }) => ({
    log: (m: string) => base.log(`[verbose] ${m}`)
  }))
)
// `verbose` still requires Logger; provide it once at the edge.
```

### Effect.updateContext

`Effect.updateContext(f)` transforms the *entire* context for the wrapped
effect. The function receives the downstream `Context` and returns a new one,
letting you add or replace several services at once. This is how you can satisfy
part of the requirements inline while leaving the rest to be provided later.

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

class Logger extends Context.Service<Logger, {
  log: (msg: string) => void
}>()("Logger") {}
class Config extends Context.Service<Config, {
  name: string
}>()("Config") {}

const program = Effect.service(Config).pipe(
  Effect.map((config) => `Hello ${config.name}!`)
)
// => Effect<string, never, Config>

// Provide Config by transforming the context, keeping Logger to be provided later
const configured = program.pipe(
  Effect.updateContext((ctx: Context.Context<Logger>) =>
    Context.add(ctx, Config, { name: "World" })
  )
)
// => Effect<string, never, Logger>   (Config supplied, Logger still required)

const runnable = configured.pipe(
  Effect.provideService(Logger, { log: console.log })
)

Effect.runPromise(runnable).then(console.log)
// => "Hello World!"
```

## Where to go next

- **Defining services** and their dependencies: [Services](https://effect.plants.sh/services-and-layers/services/).
- **Building and wiring layers** (composition, scoped resources, memoization):
  [Managing Layers](https://effect.plants.sh/services-and-layers/managing-layers/).
- **Default values** for services via `Context.Reference`:
  [References](https://effect.plants.sh/services-and-layers/references/).