Pure-Go (no CGO) SQLite driver for GORM, powered by modernc.org/sqlite.
Drop-in replacement for go-gorm/sqlite (the official CGO-based driver).
- Pure Go (no C compiler or external libraries required); cross-compiles to any Go-supported platform
- Compatible with the GORM test suite (tested on Linux, macOS, and Windows)
- JSON1, Math functions, FTS5, R-Tree, and Geopoly enabled by default
go get github.com/libtnb/sqliteimport (
"github.com/libtnb/sqlite"
"gorm.io/gorm"
)
db, err := gorm.Open(sqlite.Open("sqlite.db"), &gorm.Config{})db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})Parameters are appended to the DSN as a query string:
dsn := "sqlite.db?_txlock=immediate&_pragma=journal_mode(WAL)&_pragma=foreign_keys(1)"
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})| Parameter | Example | Description |
|---|---|---|
_pragma |
_pragma=journal_mode(WAL) |
Execute a PRAGMA statement on each new connection; can be specified multiple times. |
_txlock |
_txlock=immediate |
Transaction locking mode: deferred (default), immediate, or exclusive. |
_time_format |
_time_format=sqlite |
How time.Time is serialized to TEXT: sqlite (default, YYYY-MM-DD HH:MM:SS.SSS[+-]HH:MM) or datetime (YYYY-MM-DD HH:MM:SS). |
_time_integer_format |
_time_integer_format=unix |
Store time.Time as INTEGER instead of TEXT: unix, unix_milli, unix_micro, or unix_nano. Overrides _time_format. |
_timezone |
_timezone=UTC |
Timezone applied when reading and writing time values (parsed by time.LoadLocation). |
These are interpreted by SQLite itself, not the driver. Available when the DSN starts with file: (the driver opens connections with SQLITE_OPEN_URI).
| Parameter | Example | Description |
|---|---|---|
mode |
mode=ro |
Open mode: ro, rw, rwc (default), or memory. |
cache |
cache=shared |
Cache mode: shared or private (default). See shared cache. |
immutable |
immutable=1 |
Treat the database as read-only and unchanging; enables optimizations for read-only media. |
vfs |
vfs=unix-excl |
Use a specific VFS. |
| Pragma | Recommended | Description |
|---|---|---|
journal_mode(WAL) |
Yes | Enable WAL mode to improve concurrent read performance. |
busy_timeout(N) |
Optional | Wait up to N milliseconds on SQLITE_BUSY. Defaults to 5s; override to change. |
synchronous(NORMAL) |
With WAL | Reduce fsync calls in WAL mode with minimal durability risk. See synchronous. |
cache_size(-64000) |
Optional | Set page cache size in KiB (negative value) or pages (positive value). Defaults to -2000 (2 MiB). |
foreign_keys(1) |
If using FKs | Enable foreign key constraint enforcement (disabled by default in SQLite). |
secure_delete(1) |
If sensitive data | Overwrite deleted content with zeros instead of leaving fragments in unused pages. Small I/O overhead. |
auto_vacuum(FULL) |
Long-lived DB | Reclaim space automatically: NONE (default), FULL, or INCREMENTAL. Must be set before any tables exist. |
case_sensitive_like(1) |
Optional | Make the LIKE operator case-sensitive (default is case-insensitive for ASCII). |
recursive_triggers(1) |
If using triggers | Allow triggers to fire recursively. |
Warning
SQLite only allows one writer at a time, so concurrent writes will inevitably encounter SQLITE_BUSY (details). This cannot be fully avoided, but can be mitigated:
- Tune
busy_timeoutto control how long writers wait before failing (5s by default) - Limit the connection pool to a single connection to reduce lock contention
- Enable WAL mode to allow concurrent reads while writing
dsn := "sqlite.db?_txlock=immediate&_pragma=journal_mode(WAL)"
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})
sqlDB, _ := db.DB()
sqlDB.SetMaxOpenConns(1)
sqlDB.SetMaxIdleConns(1)Note
This serializes all database access (reads and writes). If you need concurrent reads, consider using WAL mode with a separate read-only connection pool instead. This approach does not work with :memory: databases (details).
Tests run on Linux, macOS, and Windows with the latest two Go releases. The full GORM test suite (12k+ cases) is included.