SQLite cgo driver
CGO-backed SQLite driver based on github.com/mattn/go-sqlite3, opened with production-grade PRAGMAs (WAL, foreign keys on, sensible cache size) and a single-connection pool that matches SQLite's writer model.
Overview
This is the canonical SQLite driver for Go. mattn/go-sqlite3 links against the upstream SQLite C library and exposes the full feature surface. That covers FTS5, JSON1, R-Tree, custom collations, and the latest SQLite point releases as the binding tracks them. Open opens the connection, pings it, and applies a curated set of production PRAGMAs. WAL journaling, foreign keys on, and a sensible page cache mean you do not relearn SQLite's tuning on every project. It also fixes the pool to a single connection (MaxOpenConns=1) to match SQLite's single-writer model. You hand the result straight to piko and write no PRAGMA or pool glue.
Reach for the CGO driver when you need SQLite features that the pure-Go driver lags on (FTS5 specifics, R-Tree, custom collations and aggregate functions, the latest SQLite version). It also fits when write throughput matters. The C library is the upstream reference implementation, and it targets higher throughput than the transpiled pure-Go variant on write-heavy workloads. It also fits when you ship to environments that already accept a CGO toolchain. Reach for the No-CGO driver when you need cross-compilation, scratch-image Docker builds, or to drop the C toolchain entirely. Reach for Cloudflare D1 for SQLite at the edge.
Requirements
CGO_ENABLED=1at build time. The defaultgo buildhonours this when a C toolchain is present, but you must set it explicitly for cross-compilations (for exampleGOOS=linux CGO_ENABLED=1).- A C toolchain (gcc or clang) on the build host.
mattn/go-sqlite3bundles SQLite itself, so the build does not need a system SQLite. - Write access to the directory containing the database file (the driver creates it with
0o750permissions if missing). - Compiled run modes only. This driver links a C library, so the interpreted dev mode (
dev-i) cannot load it from component code. Open the connection in your compiled host or bootstrap. The No-CGO driver is pure Go and runs underdev-i.
Configuration
import (
"context"
"piko.sh/piko/wdk/db/db_driver_sqlite_cgo"
)
connection, err := db_driver_sqlite_cgo.Open(context.Background(), "data/app.db", db_driver_sqlite_cgo.Config{
BusyTimeoutMs: 10_000, // optional, default 10000 ms
CachePages: -20_000, // optional, default -20000 (about 20 MB)
MmapSize: 64 * 1024 * 1024, // optional, default 64 MB
JournalSizeLimit: 32 * 1024 * 1024, // optional, default 32 MB
})
if err != nil {
return err
}
Open takes a context.Context first, then the file path, then the config. It pings the connection before returning, so a missing path or locked file surfaces as an error here at startup, not later at the first query.
Every Config field is optional. Passing Config{} uses the production defaults baked into the package, the right choice for most projects.
Bootstrap
import (
"piko.sh/piko"
"piko.sh/piko/wdk/db"
"piko.sh/piko/wdk/db/db_engine_sqlite"
)
ssr := piko.New(
piko.WithDatabase("primary", &db.DatabaseRegistration{
DB: connection,
EngineConfig: db_engine_sqlite.SQLite(),
MigrationFS: migrationsFS,
}),
)
Pass the pre-opened connection as DatabaseRegistration.DB. When you set DB, piko ignores DSN and DriverName and does not apply its own pool settings, because the driver already owns the connection. Do not set those fields alongside DB. The EngineConfig from db_engine_sqlite.SQLite() drives codegen, the migration dialect, and the SQL parser. It is the same engine config for both SQLite drivers, so swapping the CGO driver for the No-CGO driver needs no query changes.
Tradeoffs
The CGO build constrains where the binary goes. Cross-compiling to other platforms requires a cross-toolchain (zig cc, xx, osxcross). Docker scratch images cannot run the resulting binary without bundling a glibc or musl userspace, and CI pipelines that lack a C toolchain need adjusting. For most projects CGO is fine, and the full SQLite feature surface pays for it. Reach for the pure-Go driver when build-time portability matters more than runtime throughput.
See also
Sibling drivers:
- SQLite Driver (No CGO), pure-Go alternative; same API, slightly slower runtime, cross-compiles cleanly.
- Cloudflare D1, SQLite at the edge over HTTP.
Companion engine:
- SQLite engine, the dialect parser and migration dialect that pair with this driver.
Framework docs:
- How to use databases and queries, registering connections and running migrations.
- Database API reference, every type and function on the database service.
- About the database service, design rationale and the build-time vs runtime split.
External:
mattn/go-sqlite3, the underlying binding.- SQLite documentation, authoritative reference for SQL, PRAGMAs, and limits.