SQLx SQLite Connection Manager
A minimal wrapper around SQLx that enforces pragmatic SQLite connection policies for mobile and desktop applications. Not dependent on Tauri — usable in any Rust project needing SQLx connection management.
Features
-
Single instance per database path: Prevents duplicate pools and idle threads
-
Read pool: Concurrent read-only connections (default: 6, configurable)
-
Write connection: Single exclusive writer via
WriteGuardWait! Why? From SQLite docs: "SQLite ... will only allow one writer at any instant in time."
-
WAL mode: Enabled on first
acquire_writer()call -
Idle timeout: Connections close after 30s inactivity (configurable)
-
No perpetual caching: Zero minimum connections (prevents idle thread sprawl)
Delegates to SQLx's SqlitePoolOptions and SqliteConnectOptions wherever
possible — minimal wrapper logic.
Usage
use SqliteDatabase;
use query;
use Arc;
async
Custom Configuration
use ;
use Duration;
let config = SqliteDatabaseConfig ;
let db = connect.await?;
Migrations
Run SQLx migrations directly:
use SqliteDatabase;
// Embed migrations at compile time (reads ./migrations/*.sql)
static MIGRATOR: Migrator = migrate!;
async
Migrations are tracked in _sqlx_migrations — calling run_migrations() multiple
times is safe (already-applied migrations are skipped).
Note: When using the Tauri plugin, migrations are handled automatically via
Builder::add_migrations(). The plugin starts migrations at setup and waits for completion whenload()is called.
Attached Databases
Attach other SQLite databases to enable cross-database queries. Attached databases are connection-scoped and automatically detached when the guard is dropped.
use ;
use query;
use Arc;
async
Attached Modes
AttachedMode::ReadOnly: Attach for read access only. Can be used with both reader and writer connections.AttachedMode::ReadWrite: Attach for write access. Can only be used with writer connections. Acquires the attached database's writer lock to ensure exclusive access.
Safety Guarantees
- Lock ordering: Multiple attachments are acquired in alphabetical order by schema name to prevent deadlocks
- Mode validation: Read-only connections cannot attach databases in
read-write mode (returns
CannotAttachReadWriteToReadererror) - Automatic cleanup: SQLite automatically detaches databases when connections close; no manual cleanup required
Caution: Do not bypass this API by executing raw
ATTACH DATABASE '/path/to/db.db' AS aliasSQL commands directly. Doing so circumvents the connection manager's policies and will result in unpredictable behavior, including potential deadlocks.
API Reference
SqliteDatabase
| Method | Description |
|---|---|
connect(path, config) |
Connect/create database, returns cached Arc if already open |
read_pool() |
Get read-only pool reference |
acquire_writer() |
Acquire exclusive WriteGuard (enables WAL on first call) |
run_migrations(migrator) |
Run pending migrations from a Migrator |
close() |
Close and remove from cache |
remove() |
Close and delete database files (.db, .db-wal, .db-shm) |
WriteGuard
RAII guard for exclusive write access. Derefs to SqliteConnection. Connection
returned to pool on drop.
Attached Database Functions
| Function | Description |
|---|---|
acquire_reader_with_attached(db, specs) |
Acquire read connection with attached database(s) |
acquire_writer_with_attached(db, specs) |
Acquire writer connection with attached database(s) |
Returns AttachedConnection or AttachedWriteGuard respectively. Both guards
deref to SqliteConnection and automatically detach databases on drop.
Design Details
Read-Only Pool
The read pool opens connections with read_only(true), preventing write
operations and ensuring data integrity.
WAL Mode and Synchronous Setting
WAL mode is enabled on first acquire_writer() call (idempotent, safe across
sessions). This library sets PRAGMA synchronous = NORMAL instead of FULL:
- Performance: 2-3x faster writes — syncs only the WAL file, not after every checkpoint
- Safety in WAL mode: WAL transactions are atomic at the WAL file level;
crashes recover from intact WAL on next open (unlike rollback journal mode
where
NORMALcould cause corruption) - Mobile/Desktop context:
NORMALprovides the best balance;FULLis for unreliable storage or power-loss-mid-fsync scenarios
See SQLite WAL Performance Considerations for details.
Exclusive Writes
The write pool has max_connections=1. Callers to acquire_writer() block
asynchronously until the current WriteGuard is dropped.
Tracing
Uses tracing with release_max_level_off —
all logs compiled out of release builds. Install a tracing-subscriber in your
app to see logs during development.
Development
Follows Silvermine Rust coding standards.
&&