Vaultwarden Database Backends: How to Configure PostgreSQL, MySQL, or SQLite
Vaultwarden supports SQLite, MySQL/MariaDB, and PostgreSQL, selected at compile time via Cargo feature flags and at runtime through the DATABASE_URL environment variable.
Vaultwarden, the Rust-based Bitwarden server implementation, provides enterprise-grade password management with flexible database options. Understanding which database backends Vaultwarden supports and how to configure PostgreSQL, MySQL, or SQLite ensures your deployment matches your performance and scalability requirements. This article examines the source code in src/db/mod.rs and Cargo.toml to show exactly how database selection works and how to configure each backend properly.
Supported Database Backends
Vaultwarden can store encrypted vault data in three distinct backends. The actual driver compiled into your binary is determined by Cargo features, while runtime detection occurs through URL scheme parsing in DbConnType::from_url (lines 57‑82 of src/db/mod.rs).
SQLite
SQLite is the default choice for single-container deployments and small teams. It requires no external database server and stores data in a local file. The source code detects SQLite when DATABASE_URL contains a plain file path (e.g., data/db.sqlite3). No additional drivers or network configuration are required, and the database file is created automatically under the DATA_FOLDER directory (default ./data).
MySQL and MariaDB
MySQL and MariaDB support is enabled via the mysql Cargo feature. At runtime, Vaultwarden identifies this backend when DATABASE_URL begins with mysql://. The connection pool is established through DbPool::from_config() (lines 183‑206), which executes MySQL-specific Diesel migrations (mysql_migrations) and creates a DbConnInner::Mysql connection pool type.
PostgreSQL
PostgreSQL support is compiled using the postgresql feature flag. The backend is activated when DATABASE_URL starts with postgresql:// or postgres://. According to the source code, this triggers postgresql_migrations and instantiates the DbConnInner::Postgresql pool type, making it ideal for high-concurrency scenarios requiring robust transactional support.
Compile-Time Configuration with Cargo Features
The Cargo.toml (lines 24‑29) defines three optional features: sqlite, mysql, and postgresql. By default, all database features are disabled, requiring explicit selection during build time to minimize binary size and dependencies.
Enable your desired backend during compilation:
# SQLite only (lightweight, single-file)
cargo build --release --features sqlite
# PostgreSQL support
cargo build --release --features postgresql
# MySQL/MariaDB support
cargo build --release --features mysql
# Multiple backends (runtime selection via DATABASE_URL)
cargo build --release --features "sqlite postgresql mysql"
While you can enable multiple features simultaneously, only the backend matching your DATABASE_URL scheme will be utilized at runtime. The pre-built Docker images (vaultwarden/server) include all three drivers by default.
Runtime Configuration via DATABASE_URL
All database configuration is environment-driven. Vaultwarden reads DATABASE_URL and related pool settings from environment variables or an .env file (see the .env.template in the repository root).
URL Format Examples
Configure your .env file according to your selected backend:
- SQLite:
DATABASE_URL=data/db.sqlite3 - MySQL:
DATABASE_URL=mysql://user:[email protected]:3306/vaultwarden - PostgreSQL:
DATABASE_URL=postgresql://user:[email protected]:5432/vaultwarden
The DbConnType::from_url implementation parses these prefixes to determine which driver to initialize (lines 57‑82 of src/db/mod.rs).
Connection Pool Tuning
Vaultwarden exposes five environment variables for pool optimization, read in src/config.rs and applied in DbPool::from_config():
- DATABASE_MAX_CONNS: Maximum pooled connections (default: 10)
- DATABASE_MIN_CONNS: Minimum idle connections (default: 2)
- DATABASE_TIMEOUT: Connection acquisition timeout in seconds (default: 30)
- DATABASE_IDLE_TIMEOUT: Seconds before closing idle connections (default: 600)
- DATABASE_CONN_INIT: Optional SQL executed on each new connection (e.g.,
SET sql_mode='STRICT_TRANS_TABLES'for MySQL)
Example .env configuration for a high-traffic PostgreSQL instance:
DATABASE_URL=postgresql://vw_user:vw_pass@db:5432/vaultwarden
DATABASE_MAX_CONNS=20
DATABASE_MIN_CONNS=5
DATABASE_TIMEOUT=15
Docker and Production Examples
PostgreSQL with Docker Compose
For production deployments requiring persistent, networked storage:
version: "3.8"
services:
vaultwarden:
image: vaultwarden/server:latest
environment:
- DATABASE_URL=postgresql://vw_user:vw_pass@db:5432/vaultwarden
- DATABASE_MAX_CONNS=20
- DATABASE_TIMEOUT=15
volumes:
- ./vw-data:/data
ports:
- "8080:80"
depends_on:
- db
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=vw_user
- POSTGRES_PASSWORD=vw_pass
- POSTGRES_DB=vaultwarden
volumes:
- ./pg-data:/var/lib/postgresql/data
SQLite Write-Ahead Logging (WAL)
For improved SQLite durability and concurrency, enable WAL mode:
ENABLE_DB_WAL=true
This triggers PRAGMA journal_mode = WAL; on each connection via DbConnType::default_init_stmts in src/db/mod.rs (lines 94‑102), reducing write locks and improving performance for concurrent access.
MySQL Strict Mode Initialization
Enforce data integrity on MySQL connections using the initialization hook:
DATABASE_CONN_INIT="SET sql_mode='STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';"
The initialization string is passed to Diesel's batch_execute during connection acquisition (src/db/mod.rs, lines 35‑41).
Summary
- Vaultwarden supports SQLite, MySQL/MariaDB, and PostgreSQL through Cargo feature flags (
sqlite,mysql,postgresql) defined inCargo.tomllines 24‑29. - Runtime backend selection occurs via
DATABASE_URLparsing inDbConnType::from_url(src/db/mod.rslines 57‑82), detecting schemes likemysql://orpostgresql://. - Connection pools are configured through environment variables including
DATABASE_MAX_CONNS,DATABASE_TIMEOUT, andDATABASE_CONN_INIT. - SQLite requires no external server and supports WAL mode via
ENABLE_DB_WAL, while MySQL and PostgreSQL require reachable database instances with proper credentials. - Pre-built Docker images include all database drivers, but custom builds must specify features using
cargo build --features.
Frequently Asked Questions
Can I enable multiple database features at compile time?
Yes. You can enable multiple Cargo features simultaneously using syntax like cargo build --release --features "sqlite postgresql mysql". However, at runtime, Vaultwarden will only use the backend that matches your DATABASE_URL scheme. The DbConnType::from_url function in src/db/mod.rs (lines 57‑82) detects the specific prefix (e.g., mysql:// vs. postgresql://) and instantiates only the corresponding connection pool.
How do I enable Write-Ahead Logging (WAL) for SQLite?
Add ENABLE_DB_WAL=true to your environment variables or .env file. When this variable is set, Vaultwarden executes PRAGMA journal_mode = WAL; on each new SQLite connection via the DbConnType::default_init_stmts logic in src/db/mod.rs (lines 94‑102). WAL mode improves concurrency and durability by allowing readers to operate while a writer is active, significantly enhancing performance for multi-user scenarios.
Why does Vaultwarden require feature flags for database support?
Vaultwarden uses Cargo feature flags to keep the compiled binary size minimal and reduce unnecessary dependencies. The Cargo.toml (lines 24‑29) defines sqlite, mysql, and postgresql as optional features, all disabled by default. This modular approach ensures that if you only need SQLite, you don't compile or link MySQL or PostgreSQL client libraries into your binary.
What is the default connection pool configuration?
By default, Vaultwarden maintains a minimum of 2 idle connections and a maximum of 10 total connections, with a 30-second timeout for acquiring new connections. These values are defined in src/config.rs and applied in DbPool::from_config() in src/db/mod.rs (lines 183‑206). You can override these defaults using DATABASE_MAX_CONNS, DATABASE_MIN_CONNS, and DATABASE_TIMEOUT environment variables.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →