Pool
Shares scoped resources across fibers.
A Pool<A, E> acquires resource-backed values with a scoped effect, lets
fibers borrow them with get, can invalidate broken values, and releases all
acquired values when the pool scope closes. This module includes fixed-size
pools, pools that resize with a time-to-live policy, custom strategy pools,
per-item concurrency limits, and runtime state types used by pool strategies.
Combinators
invalidate
Invalidates the specified item so the pool can remove it and reallocate the item, lazily if needed.
When to use
Use to prevent a pooled item from being reused after it becomes unsuitable, such as a stale connection or a resource that failed a health check.
Gotchas
The item is matched with strict equality. Passing an equivalent but different object instance does nothing.
See
- get for retrieving scoped items from the pool
Signature
declare const invalidate: { <A>(item: A): <E>(self: Pool<A, E>) => Effect<void, never, Scope>; <A, E>(self: Pool<A, E>, item: A): Effect<void, never, Scope>;}Borrows an item while an effect runs and returns it when the effect exits.
When to use
Use when an item is needed by one effect. Unlike Effect.scoped with
get, this avoids allocating a scope and registering a finalizer.
See
- get for borrowing an item for the lifetime of a scope
Signature
declare const use: { <A, B, E2, R2>(f: (item: A) => Effect<B, E2, R2>): <E>(self: Pool<A, E>) => Effect<B, E2 | E, R2>; <A, E, B, E2, R2>(self: Pool<A, E>, f: (item: A) => Effect<B, E2, R2>): Effect<B, E | E2, R2>;}Example
(Running a single operation with a pooled item)
import { Effect, Pool } from "effect"
const program = Effect.scoped( Effect.flatMap( Pool.make({ acquire: Effect.succeed("resource"), size: 2 }), (pool) => Pool.use(pool, (item) => Effect.succeed(item.length)) ))
await Effect.runPromise(program) // => 8Constructors
Makes a new pool of the specified fixed size.
When to use
Use when you need a fixed-size pool with no growth or shrinkage.
Details
The pool is returned in a Scope, which governs the lifetime of the pool.
When the pool is shutdown because the Scope is closed, the individual
items allocated by the pool will be released in some unspecified order.
By setting the concurrency parameter, you can control the level of concurrent
access per pool item. By default, the number of permits is set to 1.
targetUtilization determines when to create new pool items. It is a value
between 0 and 1, where 1 means only create new pool items when all the existing
items are fully utilized.
A targetUtilization of 0.5 will create new pool items when the existing items are
50% utilized.
See
- makeWithTTL for pools with min/max sizes and a TTL-based shrinking policy
- makeWithStrategy for pools with a custom resizing and reclamation strategy
Signature
declare function make<A, E, R>(options: { readonly acquire: Effect<A, E, R>; readonly concurrency?: number; readonly size: number; readonly targetUtilization?: number;}): Effect<Pool<A, E>, never, Scope | R>makeWithStrategy
Creates a scoped pool using a custom resizing and reclamation strategy.
When to use
Use to build a pool whose item lifecycle is controlled by an explicit
Strategy, such as custom background resizing, replacement, or reclamation.
Details
The returned pool requires Scope; closing the scope shuts down the pool and
releases allocated items.
See
- make for fixed-size pools without custom resizing or reclamation
- makeWithTTL for min/max pools that shrink excess items with a TTL policy
- Strategy for the custom strategy contract consumed by this constructor
Signature
declare function makeWithStrategy<A, E, R>(options: { readonly acquire: Effect<A, E, R>; readonly concurrency?: number; readonly max: number; readonly min: number; readonly strategy: Strategy<A, E>; readonly targetUtilization?: number;}): Effect<Pool<A, E>, never, Scope | R>makeWithTTL
Creates a scoped pool with minimum and maximum sizes and a time-to-live policy for shrinking unused excess items.
When to use
Use to create an elastic scoped pool that can grow up to a maximum size and later reclaim unused excess items.
Details
The returned pool requires Scope; when that scope is closed, allocated
items are released in an unspecified order. concurrency controls how many
fibers may use each pool item at once and defaults to 1.
targetUtilization controls when new items are created and is clamped by the
pool implementation. A value of 1 waits until existing items are fully
utilized before creating more items.
timeToLiveStrategy controls when excess items expire: "creation" measures
from item creation, while "usage" measures from pool usage. The default is
"usage".
Signature
declare function makeWithTTL<A, E, R>(options: { readonly acquire: Effect<A, E, R>; readonly concurrency?: number; readonly max: number; readonly min: number; readonly targetUtilization?: number; readonly timeToLive: Input; readonly timeToLiveStrategy?: "creation" | "usage";}): Effect<Pool<A, E>, never, Scope | R>Example
(Creating a connection pool)
import { Duration, Effect, Pool } from "effect"
interface Connection { readonly execute: (sql: string) => Effect.Effect<ReadonlyArray<string>> readonly close: Effect.Effect<void>}
const acquireDBConnection = Effect.acquireRelease( Effect.succeed({ execute: (sql) => Effect.succeed([`executed: ${sql}`]), close: Effect.void } satisfies Connection), (connection) => connection.close)
const program = Effect.scoped( Effect.flatMap( Pool.makeWithTTL({ acquire: acquireDBConnection, min: 10, max: 20, timeToLive: Duration.seconds(60) }), (pool) => Effect.flatMap(Pool.get(pool), (connection) => connection.execute("select 1")) ))
await Effect.runPromise(program) // => ["executed: select 1"]Getters
Retrieves an item from the pool in a scoped effect.
When to use
Use to borrow a pooled resource for the lifetime of the current scope so it is automatically returned when that scope closes.
Details
The returned effect waits for an available item when the pool is at capacity. If acquiring a new item fails, the effect fails with the acquisition error.
Gotchas
Retrying a failed get can repeat the acquisition attempt.
See
- invalidate for removing an unhealthy item from future reuse
Signature
declare function get<A, E>(self: Pool<A, E>): Effect<A, E, Scope>Guards
Returns true if the specified value is a Pool, false otherwise.
When to use
Use to validate unknown values at runtime boundaries before treating them as
Pool values.
Details
This predicate narrows the input to Pool<unknown, unknown>.
Signature
declare function isPool(u: unknown): u is Pool<unknown, unknown>Models
Normalized configuration used by a Pool.
When to use
Use as the normalized, read-only description of how a pool acquires, sizes, shares, and resizes its items after construction.
Details
The config stores the acquire effect, size bounds, per-item concurrency, target utilization, and resizing strategy used by the pool implementation.
See
Signature
interface Config<A, E> { readonly acquire: Effect<A, E, Scope>; readonly concurrency: number; readonly isFixed: boolean; readonly maxSize: number; readonly minSize: number; readonly strategy: Strategy<A, E>; readonly targetUtilization: number;}A Pool<A, E> is a pool of items of type A, each of which may be
associated with the acquisition and release of resources. An attempt to get
an item A from a pool may fail with an error of type E.
When to use
Use when you need to share a bounded set of scoped resources across fibers while the pool manages acquisition, reuse, and release.
See
- make for creating a pool with size bounds
- makeWithTTL for creating a pool with idle item expiration
- makeWithStrategy for creating a pool with a custom strategy
- get for acquiring an item from a pool
- invalidate for removing a broken item from the pool
Signature
interface Pool<in out A, in out E = never> extends Pipeable { readonly "~effect/Pool": "~effect/Pool"; readonly config: Config<A, E>; readonly state: State<A, E>;}Internal record for a value managed by a Pool.
When to use
Use when implementing a custom pool Strategy that needs to inspect
acquired items, track reference counts, or return reclaimable items to the
pool.
Details
Each item stores the acquisition Exit, its finalizer, the current
reference count, and whether automatic reclaiming has been disabled because
the item was invalidated.
See
Signature
interface PoolItem<A, E> { availableNext: PoolItem<A, E> | undefined; availablePrevious: PoolItem<A, E> | undefined; disableReclaim: boolean; readonly exit: Exit<A, E>; finalizer: Effect<void>; isAvailable: boolean; refCount: number; release: (exit: Exit<any, any>) => Effect<void>;}Mutable runtime state maintained by a Pool.
When to use
Use when you need to inspect or support the runtime state backing a Pool,
including its scope, item sets, semaphores, waiters, invalidation tracking,
and shutdown flag.
Details
This state is exposed for inspection and implementation support. User code should prefer the high-level pool operations.
See
- Pool for the pool value exposing this state
- PoolItem for the entries stored in the runtime item sets
- get for acquiring items through the high-level API
- invalidate for invalidating items through the high-level API
Signature
interface State<A, E> { availableHead: PoolItem<A, E> | undefined; availableTail: PoolItem<A, E> | undefined; readonly invalidated: Set<PoolItem<A, E>>; isShuttingDown: boolean; readonly items: Set<PoolItem<A, E>>; readonly resizeSemaphore: Semaphore; readonly scope: Scope; usage: number; readonly waiters: Set<() => void>;}Strategy used by a Pool to manage background resizing and item
reclamation.
When to use
Use when defining a custom pool lifecycle policy that needs to run background work, observe acquired items, or choose items for reclamation.
Details
run starts any strategy-specific background work, onAcquire is invoked
when an item is acquired, and reclaim selects an item that can be removed
or replaced.
See
- makeWithStrategy for constructing a pool from a custom
Strategy
Signature
interface Strategy<A, E> { readonly onAcquire: (item: PoolItem<A, E>) => Effect<void>; readonly reclaim: (pool: Pool<A, E>) => Effect<PoolItem<A, E> | undefined>; readonly run: (pool: Pool<A, E>) => Effect<void>;}