Skip to main content

Object Pool

Object Pool reuses costly objects like connections and threads from a bounded managed set instead of recreating them, improving performance and capping resources. State reset and sizing are key concerns.

Type
Creational
When to Use
Expensive Object Creation, High Allocation Churn, Bounded Resource Limit, Frequent Reuse

The Object Pool pattern keeps a set of initialized objects ready for reuse rather than allocating and discarding them on each request. It targets situations where object creation is expensive — database connections, threads, large buffers, or sockets — and where churn would otherwise dominate runtime cost and stress the garbage collector or operating system.

How It Works

A pool manages a collection of reusable objects. A client acquires an object from the pool, uses it, and releases it back when done; the pool resets the object's state and makes it available again. The pool typically enforces a maximum size: when all objects are in use, an acquiring client either waits, receives an error, or triggers controlled growth up to a cap. Idle objects may be validated, refreshed, or evicted after a timeout.

Correct lifecycle handling is essential. Released objects must be cleaned so no stale state leaks to the next user, and clients must reliably return objects — usually via try/finally or a using/with block — or the pool leaks and exhausts.

When to Use It

Use a pool when objects are costly to create or hold scarce external resources, when they are requested frequently and used briefly, and when bounding concurrency is desirable. Connection pools (JDBC/HikariCP, PgBouncer-style pooling), thread pools, and byte-buffer pools are canonical examples.

Do not pool cheap, stateless objects; modern allocators and garbage collectors handle short-lived objects efficiently, and a needless pool adds contention and complexity. Profiling should justify pooling before you introduce it.

Trade-offs

Pooling amortizes expensive setup, smooths latency by avoiding cold starts, and caps resource usage to protect downstream systems. For connections and threads it is often essential to stability.

The risks are real. Improperly reset objects cause data leakage or correctness bugs that are hard to trace. Pools add synchronization that can become a contention point. Sizing is a tuning problem: too small starves throughput, too large wastes resources or overwhelms the backend. Pooled objects can also hold connections open in ways that complicate failover. Leaked objects — never returned — slowly drain the pool.

Related Patterns

Object Pool resembles Singleton in that the pool itself is usually a single shared manager, and it is often created through a Factory Method. It complements the Bulkhead pattern, which also bounds resource consumption to isolate failures. Flyweight shares objects too, but for immutable shared state rather than exclusive temporary checkout.

Example

A web service uses a database connection pool sized to 20. Each request acquires a connection, runs queries, and returns it in a finally block. Under load the pool reuses connections instead of paying the TCP and authentication cost per request, and it caps the database at 20 concurrent connections, protecting it from overload. If all 20 are busy, additional requests briefly wait rather than opening unbounded connections.