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.

SQLx’s SQLite driver wraps the libsqlite3 C library via libsqlite3-sys. Unlike the PostgreSQL and MySQL drivers, it is not pure Rust — SQLite has no async-native client protocol, so a background worker thread bridges the blocking SQLite API to the async executor. The driver supports in-memory databases, WAL mode, custom PRAGMAs, foreign key enforcement, and optional extension loading.

Feature flags

Two mutually exclusive base feature flags control how libsqlite3 is linked:
FeatureBehaviour
sqliteBundles and statically links the SQLite amalgamation. No system SQLite required. (recommended)
sqlite-unbundledLinks against the system-installed libsqlite3. Version 3.20.0 or newer recommended. May use bindgen at build time.
[dependencies]
# Bundled SQLite (most common)
sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite"] }

# System SQLite
sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite-unbundled"] }
The sqlite feature also enables sqlite-load-extension and sqlite-unlock-notify automatically.
SQLx uses #![deny(unsafe_code)] globally, but downgrade this to #![allow(unsafe_code)] on the sqlx::sqlite module because the SQLite C API requires unsafe. The rest of SQLx remains fully safe.

Additional SQLite features

FeatureWhat it enables
sqlite-load-extensionSqliteConnectOptions::extension() for loading .so/.dll extensions
sqlite-preupdate-hooksqlite3_preupdate_hook API (requires sqlite-bundled or a SQLite build with SQLITE_ENABLE_PREUPDATE_HOOK)
sqlite-deserializeSqliteConnection::serialize() / ::deserialize() in-memory serialization
regexpRegisters a REGEXP SQL function backed by the regex crate

Connection URLs

URLResult
sqlite::memory:Unnamed in-memory database (destroyed when the connection closes)
sqlite:data.dbFile data.db in the current directory
sqlite://data.dbFile data.db in the current directory
sqlite:///data.dbAbsolute path /data.db
sqlite://data.db?mode=roRead-only access to data.db
use sqlx::SqlitePool;

// In-memory database
let pool = SqlitePool::connect("sqlite::memory:").await?;

// File-based database
let pool = SqlitePool::connect("sqlite://app.db").await?;

SqliteConnectOptions

SqliteConnectOptions exposes fine-grained control over connection behaviour. It also implements FromStr, so you can parse a URL string and then apply additional configuration.
use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePool};
use std::str::FromStr;

let opts = SqliteConnectOptions::from_str("sqlite://app.db")?
    .create_if_missing(true)
    .journal_mode(SqliteJournalMode::Wal)
    .foreign_keys(true);

let pool = SqlitePool::connect_with(opts).await?;

Key options

Option / methodDefaultDescription
filename:memory:Path to the database file
in_memoryfalseOpen a named or anonymous in-memory database
create_if_missingfalseCreate the file if it does not exist
read_onlyfalseOpen in read-only mode
foreign_keysONEnforce foreign key constraints (SQLx default; SQLite default is OFF)
journal_modeNone (SQLite default: DELETE)Journal mode; WAL is recommended for concurrent read workloads
synchronousFULLFsync policy; NORMAL is sufficient in WAL mode
busy_timeout5sHow long to wait on a locked database before returning SQLITE_BUSY
statement_cache_capacity100LRU prepared-statement cache size per connection
shared_cachefalseEnable SQLite shared cache mode
immutablefalseSignal SQLite that the file is on read-only media (disables locking)
optimize_on_closeDisabledRun PRAGMA optimize; before closing each connection

In-memory databases

Each in-memory database is private to a single connection by default. To share one in-memory database across a pool, use a named in-memory URI with shared cache, or build a pool capped to a single connection:
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};

// Single-connection pool keeps the same in-memory database alive
let pool = SqlitePoolOptions::new()
    .max_connections(1)
    .connect("sqlite::memory:")
    .await?;
If you use max_connections > 1 with sqlite::memory:, each connection gets its own independent database. Schema changes made on one connection will not be visible to others.

WAL mode

Write-Ahead Logging (WAL) mode significantly improves concurrent read performance because readers do not block writers and writers do not block readers. It is the recommended journal mode for most applications. WAL mode is a permanent, per-file setting. Once a database file is opened in WAL mode it retains that setting across all future connections. SQLx intentionally does not set a journal_mode by default to avoid unintentionally changing a database into or out of WAL mode (which requires an exclusive lock).
use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqliteSynchronous};
use std::str::FromStr;

let opts = SqliteConnectOptions::from_str("sqlite://app.db")?
    .create_if_missing(true)
    .journal_mode(SqliteJournalMode::Wal)
    // NORMAL is safe and faster than FULL in WAL mode
    .synchronous(SqliteSynchronous::Normal);
All databases created by sqlx-cli (e.g. via sqlx migrate run) are created in WAL mode. If you manage database files outside of SQLx, set WAL mode manually the first time you open a new database.

Custom PRAGMAs

Any SQLite PRAGMA can be set at connection time using .pragma():
use sqlx::sqlite::SqliteConnectOptions;
use std::str::FromStr;

let opts = SqliteConnectOptions::from_str("sqlite://app.db")?
    .pragma("cache_size", "-65536")  // 64 MiB page cache
    .pragma("mmap_size", "268435456"); // 256 MiB memory-mapped I/O

Loading extensions

Enable the sqlite-load-extension feature, then call .extension() inside an unsafe block. Extension loading is automatically disabled before connect() returns.
use sqlx::sqlite::SqliteConnectOptions;
use std::str::FromStr;

let opts = SqliteConnectOptions::from_str("sqlite://app.db")?;

// SAFETY: only load extensions you trust
let opts = unsafe {
    opts.extension("mod_spatialite")
        .extension("vsv")
};

let pool = sqlx::SqlitePool::connect_with(opts).await?;
Loading extensions causes arbitrary shared libraries to be executed at runtime. Only load extensions from sources you trust.

Type mapping

SQLite uses a flexible, “type-affinity” system. SQLx maps SQLite’s storage classes to Rust types as follows:
SQLite affinity / typeRust type
INTEGERi64, i32, i16, i8, u64, u32, u16, u8, bool
REALf64, f32
TEXTString, &str
BLOBVec<u8>, &[u8]
TEXT (ISO 8601)chrono::NaiveDateTime / NaiveDate / NaiveTime (feature: chrono)
TEXT (RFC 3339)chrono::DateTime<Utc> (feature: chrono)
TEXT (UUID)uuid::Uuid (feature: uuid)
TEXT / BLOB (JSON)serde_json::Value (feature: json)
SQLite stores BOOLEAN as an integer (0 or 1). SQLx maps this transparently; bind a Rust bool and it will be encoded as 0 or 1.

Build docs developers (and LLMs) love