Skip to content
Effect Days 2026 Get your ticket

LayerMap

Caches scoped services selected by key and built from layers.

A LayerMap<K, I, E> turns a key into a cached service Context<I> and exposes that context as either a Layer or a scoped effect. Entries can be invalidated explicitly or released after they sit unused. This is useful for keyed resource families such as tenant clients, regional connections, or environment-specific services.

6 exports Added in v3.14.0 Source

Constructors

fromRecord

Added in v3.14.0 Source

Creates a LayerMap from a record of predefined layers.

Details

The record keys become the keys accepted by the returned LayerMap, and the record values are the layers built for those keys.

Signature

declare function fromRecord<Layers extends Record<string, Layer<any, any, any>>, Preload extends boolean = false>(layers: Layers, options?: {
readonly idleTimeToLive?: IdleTimeToLiveInput<keyof Layers>;
readonly preload?: Preload;
}): Effect<LayerMap<keyof Layers, Success<Layers[keyof Layers]>, Error<Layers[keyof Layers]>>, Preload extends true ? Error<Layers[keyof Layers]> : never, Scope | Layers[keyof Layers] extends Layer<_A, _E, _R> ? _R : never>

Example

(Creating a layer map from a record)

import { Context, Effect, Layer, LayerMap } from "effect"
// Define a service key
const Database = Context.Service<{
readonly query: (sql: string) => Effect.Effect<string>
}>("Database")
// Create predefined layers
const layers = {
development: Layer.succeed(Database)({
query: Effect.fn("DevDatabase.query")((sql) => Effect.succeed(`DEV: ${sql}`))
}),
production: Layer.succeed(Database)({
query: Effect.fn("ProdDatabase.query")((sql) => Effect.succeed(`PROD: ${sql}`))
})
} as const
// Create a LayerMap from the record
const program = Effect.gen(function*() {
const layerMap = yield* LayerMap.fromRecord(layers, {
idleTimeToLive: "10 seconds"
})
const development = yield* Effect.provide(
Database.use((database) => database.query("SELECT 1")),
layerMap.get("development")
)
const production = yield* Effect.provide(
Database.use((database) => database.query("SELECT 1")),
layerMap.get("production")
)
return { development, production }
})
await Effect.runPromise(Effect.scoped(program)) // => { development: "DEV: SELECT 1", production: "PROD: SELECT 1" }

make

Added in v3.14.0 Source

Creates a LayerMap that dynamically provides resources based on a key.

Signature

declare const make: <K, L extends Layer.Layer<any, any, any>, PreloadKeys extends Iterable<K> | undefined = undefined>(lookup: (key: K) => L, options?: {
readonly idleTimeToLive?: IdleTimeToLiveInput<K>;
readonly preloadKeys?: PreloadKeys;
}) => Effect.Effect<LayerMap<K, Layer.Success<L>, Layer.Error<L>>, PreloadKeys extends undefined ? never : Layer.Error<L>, Scope.Scope | Layer.Services<L>>

Example

(Creating a layer map)

import { Context, Effect, Layer, LayerMap } from "effect"
// Define a service key
const DatabaseService = Context.Service<{
readonly query: (sql: string) => Effect.Effect<string>
}>("Database")
// Create a LayerMap that provides different database configurations
const program = Effect.gen(function*() {
const layerMap = yield* LayerMap.make(
(env: string) =>
Layer.succeed(DatabaseService)({
query: Effect.fn("DatabaseService.query")((sql) => Effect.succeed(`${env}: ${sql}`))
}),
{ idleTimeToLive: "5 seconds" }
)
// Get a layer for a specific environment
const devLayer = layerMap.get("development")
// Use the layer to provide the service
return yield* Effect.provide(
Effect.gen(function*() {
const db = yield* DatabaseService
return yield* db.query("SELECT * FROM users")
}),
devLayer
)
})
await Effect.runPromise(Effect.scoped(program)) // => "development: SELECT * FROM users"

Models

LayerMap interface

Added in v3.14.0 Source

A scoped, keyed map of layer-built service contexts.

Details

A LayerMap builds resources for a key on demand, exposes them as a Layer or scoped Context, and can invalidate cached resources for a key.

Signature

interface LayerMap<in out K, in out I, in out E = never> {
readonly "~effect/LayerMap": "~effect/LayerMap";
readonly rcMap: RcMap<K, Context<I>, E>;
contextEffect(key: K): Effect<Context<I>, E, Scope>;
contextEffectOption(key: K): Effect<Option<Context<I>>, E, Scope>;
get(key: K): Layer<I, E>;
invalidate(key: K): Effect<void>;
}

Example

(Managing keyed layers)

import { Context, Effect, Layer, LayerMap } from "effect"
// Define a service key
const DatabaseService = Context.Service<{
readonly query: (sql: string) => Effect.Effect<string>
}>("Database")
// Create a LayerMap that provides different database configurations
const createDatabaseLayerMap = LayerMap.make((env: string) =>
Layer.succeed(DatabaseService)({
query: Effect.fn("DatabaseService.query")((sql) => Effect.succeed(`${env}: ${sql}`))
})
)
// Use the LayerMap
const program = Effect.gen(function*() {
const layerMap = yield* createDatabaseLayerMap
// Get a layer for a specific environment
const development = yield* Effect.provide(
DatabaseService.use((database) => database.query("SELECT 1")),
layerMap.get("development")
)
// Get context directly
const productionContext = yield* layerMap.contextEffect("production")
const production = yield* Context.get(productionContext, DatabaseService).query("SELECT 1")
// Invalidate a cached layer
yield* layerMap.invalidate("development")
return { development, production }
})
await Effect.runPromise(Effect.scoped(program)) // => { development: "development: SELECT 1", production: "production: SELECT 1" }

Other

Service

Added in v3.14.0 Source

Type helpers for values created with LayerMap.Service.

Services

Service

Added in v3.14.0 Source

Create a LayerMap service that provides a dynamic set of resources based on a key.

Signature

declare function Service<Self>(): <Id extends string, Options extends NoExcessProperties<{
readonly dependencies?: readonly Array<Layer<any, any, any>>;
readonly idleTimeToLive?: IdleTimeToLiveInput<any>;
readonly lookup: (key: any) => Layer<any, any, any>;
readonly preloadKeys?: Iterable<Options extends {
readonly lookup: (key: K) => any;
} ? K : never, any, any>;
}, Options> | NoExcessProperties<{
readonly dependencies?: readonly Array<Layer<any, any, any>>;
readonly idleTimeToLive?: IdleTimeToLiveInput<any>;
readonly layers: Record<string, Layer.Layer<any, any, any>>;
readonly preload?: boolean;
}, Options>>(id: Id, options: Options) => TagClass<Self, Id, Options extends {
readonly lookup: (key: K) => any;
} ? K : Options extends {
readonly layers: Layers;
} ? keyof Layers : never, Success<Options>, Options extends {
readonly preload: true;
} ? never : Error<Options>, Services<Options>, Options extends {
readonly preload: true;
} ? Error<Options> : Options extends {
readonly preloadKeys: Iterable<any>;
} ? Error<Options> : never, Options extends {
readonly dependencies: readonly Array<Layer<any, any, any>>;
} ? Options["dependencies"][number] : never>

Example

(Defining a layer map service)

import { Context, Effect, Layer, LayerMap } from "effect"
// Define a service key
const Greeter = Context.Service<{
readonly greet: Effect.Effect<string>
}>("Greeter")
// Create a service that wraps a LayerMap
class GreeterMap extends LayerMap.Service<GreeterMap>()("GreeterMap", {
// Define the lookup function for the layer map
lookup: (name: string) =>
Layer.succeed(Greeter)({
greet: Effect.succeed(`Hello, ${name}!`)
}),
// If a layer is not used for a certain amount of time, it can be removed
idleTimeToLive: "5 seconds"
}) {}
// Usage
const program = Effect.gen(function*() {
// Access and use the Greeter service
const greeter = yield* Greeter
return yield* greeter.greet
}).pipe(
// Use the GreeterMap service to provide a variant of the Greeter service
Effect.provide(GreeterMap.get("John"))
).pipe(
// Provide the GreeterMap layer
Effect.provide(GreeterMap.layer)
)
await Effect.runPromise(program) // => "Hello, John!"

TagClass interface

Added in v3.14.0 Source

Service class shape produced by LayerMap.Service.

When to use

Use as the public type for classes returned by LayerMap.Service when an API needs to accept, return, or alias the generated service class and its static helpers.

Details

It combines a Context.Service tag for the LayerMap with default layers and helper accessors for retrieving, using, and invalidating keyed resources.

See

  • Service for creating concrete LayerMap service classes

Signature

interface TagClass<in out Self, in out Id extends string, in out K, in out I, in out E, in out R, in out LE, in out Deps extends Layer.Layer<any, any, any>> extends ServiceClass<Self, Id, LayerMap<K, I, E>> {
constructor(_: never);
readonly contextEffect: (key: K) => Effect<Context<I>, E, Scope | Self>;
readonly contextEffectOption: (key: K) => Effect<Option<Context<I>>, E, Scope | Self>;
readonly get: (key: K) => Layer<I, E, Self>;
readonly invalidate: (key: K) => Effect<void, never, Self>;
readonly layer: Layer<Self, LE | Deps extends Layer<_A, _E, _R> ? _E : never, Exclude<R, Deps extends Layer<_A, _E, _R> ? _A : never> | Deps extends Layer<_A, _E, _R> ? _R : never>;
readonly layerNoDeps: Layer<Self, LE, R>;
}