Skip to main content
Requires feature = "pool". (AsyncPool additionally needs async.)
The pool feature provides an r2d2 connection pool whose connections all share one Database — so an in-memory pool observes a single consistent database, not one isolated database per slot.

Managers

DuckDbConnectionManager is the r2d2::ManageConnection that mints connections from a shared Database: database() -> &Database returns the shared database. The manager is Clone + Send + Sync.

Type aliases and re-exports

The pool module re-exports r2d2 types so you don’t depend on r2d2 directly:
  • Pool = r2d2::Pool<DuckDbConnectionManager>.
  • PooledConnection = r2d2::PooledConnection<DuckDbConnectionManager> — derefs to Connection.
  • PoolBuilder = r2d2::Builder, PoolError = r2d2::Error, PoolState = r2d2::State ({ connections, idle_connections }).
r2d2’s builder and checkout return r2d2’s own error type, not Error. Map it with .map_err(|e| Error::Pool(e.to_string())) (there is an Error::Pool(String) variant for exactly this).

Async pool

AsyncPool needs both the async and pool features.
AsyncPool wraps a Pool. with is the primitive: it checks a connection out, runs a closure on a blocking thread, and releases the checkout when the closure returns.
with is deliberately the only way to touch a pooled connection. Holding a pooled-connection guard across an .await would pin a pool slot for the whole suspension — the classic async-pool deadlock — and a transaction must not span an .await. Keep the whole unit of work inside the closure.
Also available: pool() -> &Pool, state().await -> PoolState, execute_batch(sql).await, execute(sql).await -> ResultSet, and execute_with(sql, Vec<DuckValue>).await -> ResultSet.

See also