Skip to main content
With feature = "r2d2", DuckDbConnection works with r2d2 pooling. There are two managers — pick based on whether pooled connections must observe the same data. Verified against crates/better-duck-diesel/src/pool.rs.

Choosing a manager

Health checks

DuckDbConnection implements R2D2Connection:
  • .ping() runs SELECT 1 to validate a connection.
  • .is_broken() checks the transaction manager.
r2d2 uses these automatically (test_on_check_out, connection_customizer, etc.).

Per-connection setup with on_connect

UDF registration and LOADing extensions live on a single DuckDB connection, not the shared database, so they must run on every pooled connection. SharedDuckDbConnectionManager provides an on_connect hook for exactly this:
The closure receives &mut DuckDbConnection and returns better_duck_core::error::Result<()>; an Err fails opening that connection. Use it to:
Because registration and extension loading are per-connection, forgetting on_connect yields a pool where only some connections have your UDFs/extensions — queries then fail intermittently depending on which connection pool.get() hands you.

Core pooling and async

Below the ORM, better-duck-core has its own pool and async features (AsyncPool, AsyncDatabase). If you need async DB calls, reach them through the core connection — the Diesel surface is synchronous. See Core async & pooling.

See also

Calling your own UDFs

Register per connection in on_connect.

Spatial

ensure_loaded in on_connect.

Installation & setup

inner_mut() and sharing a Database.

Core async & pooling

The async facade below the ORM.