Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/launchbadge/sqlx/llms.txt

Use this file to discover all available pages before exploring further.

A connection pool holds a bounded set of reusable database connections and hands them out on demand. Using a pool is almost always preferable to opening individual connections — it amortizes connection setup cost, enforces a hard concurrency limit, and automatically evicts unhealthy connections.
Pool is cheaply cloneable (it wraps an Arc internally). Clone it freely to share a single pool across multiple tasks or across your application state.

Type aliases

SQLx re-exports Pool<DB> with database-specific type aliases for convenience.
Type aliasDatabase
sqlx::PgPoolPostgreSQL
sqlx::MySqlPoolMySQL / MariaDB
sqlx::SqlitePoolSQLite
sqlx::AnyPoolAny (runtime-selected driver)
Use the alias instead of the generic form when you only target one database — the code is shorter and error messages are easier to read.

Pool::connect

pub async fn connect(url: &str) -> Result<Self, Error>
Opens a pool and eagerly establishes min_connections connections (default 0), returning as soon as the first connection succeeds. The connection URL format is database-specific.
let pool = sqlx::PgPool::connect("postgres://user:pass@localhost/mydb").await?;
Read the URL from an environment variable in production rather than hardcoding it.
let pool = sqlx::PgPool::connect(&std::env::var("DATABASE_URL")?).await?;

Pool::connect_lazy

pub fn connect_lazy(url: &str) -> Result<Self, Error>
Creates a pool without opening any connections immediately. Connections are opened on the first acquire() call. Useful when you want to initialize pool state at startup without blocking on the database.
let pool = sqlx::PgPool::connect_lazy("postgres://user:pass@localhost/mydb")?;

Pool::acquire

pub async fn acquire(&self) -> Result<PoolConnection<DB>, Error>
Retrieves a connection from the pool, waiting up to acquire_timeout (default 30 s) if all connections are busy. The connection is returned to the pool automatically when the PoolConnection guard is dropped.
let mut conn = pool.acquire().await?;
sqlx::query("UPDATE counters SET n = n + 1").execute(&mut *conn).await?;
// conn is returned to the pool here

Pool::begin

pub async fn begin(&self) -> Result<Transaction<'static, DB>, Error>
Acquires a connection and immediately begins a database transaction. Returns a Transaction guard; call .commit() to commit or let it drop to roll back.
let mut tx = pool.begin().await?;

sqlx::query("INSERT INTO orders(total) VALUES ($1)").bind(99_i64)
    .execute(&mut *tx)
    .await?;

tx.commit().await?;

Pool::close

pub async fn close(&self)
Signals the pool to stop accepting new connections and waits for all currently checked-out connections to be returned and closed. Call this during graceful shutdown.
pool.close().await;

PoolOptions

PoolOptions<DB> is the builder used to configure a pool before connecting. Every setter takes self by value and returns Self, so calls can be chained.
use sqlx::postgres::PgPoolOptions;

let pool = PgPoolOptions::new()
    .max_connections(20)
    .min_connections(2)
    .acquire_timeout(std::time::Duration::from_secs(5))
    .connect("postgres://user:pass@localhost/mydb")
    .await?;

Configuration reference

OptionDefaultDescription
max_connections10Maximum number of open connections in the pool.
min_connections0Connections to maintain at all times; new ones are opened in the background if the count falls below this.
acquire_timeout30 sMaximum time to wait for a free connection before returning Error::PoolTimedOut.
idle_timeout10 minHow long a connection may sit idle before it is closed and removed. Set to None to disable.
max_lifetime30 minMaximum total age of any connection. Connections older than this are closed on release. Set to None to disable.
test_before_acquiretrueWhether to send a health-check ping before returning a connection from the idle queue.
The default of max_connections = 10 is intentionally conservative. Most production workloads should raise this value; check your database’s per-user connection limit first.

Lifecycle hooks

Hooks let you run async code at key points in a connection’s lifetime. Each hook receives a mutable reference to the connection and a [PoolConnectionMetadata] struct containing age and idle_for durations.

after_connect

Called once, immediately after a new connection is opened. Use it to set session-level settings (e.g., SET search_path, SET time zone).
use sqlx::postgres::PgPoolOptions;

let pool = PgPoolOptions::new()
    .after_connect(|conn, _meta| Box::pin(async move {
        sqlx::query("SET search_path = myschema")
            .execute(conn)
            .await?;
        Ok(())
    }))
    .connect("postgres://user:pass@localhost/mydb")
    .await?;

before_acquire

Called each time a connection is about to be handed out. Return Ok(true) to allow the connection, Ok(false) to close it and acquire a fresh one, or Err(_) to propagate an error.
.before_acquire(|conn, meta| Box::pin(async move {
    if meta.age > std::time::Duration::from_secs(3600) {
        // Force a fresh connection after 1 hour
        return Ok(false);
    }
    Ok(true)
}))

after_release

Called each time a connection is returned to the pool. Return Ok(true) to keep it, Ok(false) to discard it.
.after_release(|_conn, _meta| Box::pin(async move {
    // Could inspect connection state here
    Ok(true)
}))
All hooks must return BoxFuture<'_, Result<_, Error>>. Wrap your async block with Box::pin(async move { ... }).

Build docs developers (and LLMs) love