go-sqlite3

A self-contained CGO driver that brings SQLite3 to Go's standard database/sql interface.

Library
Go
vv1.14.52
9,260 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
84 /100 Excellent
Development Activity 84
Maintenance 72
Community 80
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
78 /100 Good
Architecture 86
Code Quality 87
Innovation 82
Learning Curve 55

go-sqlite3 is the de facto CGO binding for embedding SQLite3 in Go programs. It implements the full database/sql/driver interface — Open, Exec, Query, Prepare, and Begin — so any code written against Go’s standard database/sql package can talk to a local SQLite file or in-memory database by simply importing the driver and calling sql.Open(“sqlite3”, dsn).

Rather than depending on a system-installed libsqlite3, the package vendors an amalgamated SQLite3 C source (sqlite3-binding.c/h) and compiles it directly into the Go binary via cgo, producing self-contained, reproducible builds across Linux, macOS, and Windows. Consumers who prefer to link against the system library instead can opt in with the libsqlite3 build tag.

Beyond the base driver interface, go-sqlite3 exposes SQLite-specific extension points not available through database/sql alone: registering custom Go functions and aggregates as SQL functions, collation sequences, and commit/rollback/update/authorizer/pre-update hooks. A large set of optional SQLite compile-time features — FTS5 full-text search, JSON functions, ICU, virtual tables, user authentication, serialization, and more — are each gated behind their own Go build tag, so a default build stays lean and only pulls in the C code a consumer actually asks for.

What You Get

  • database/sql driver - register once with sql.Register/blank import, then use the standard library’s sql.DB, sql.Rows, and sql.Tx APIs against SQLite exactly like any other driver.
  • Self-contained builds - the SQLite C amalgamation is vendored and compiled via cgo, so there’s no system libsqlite3 dependency by default (with an opt-in libsqlite3 build tag for linking against the system library instead).
  • Rich DSN options - dozens of SQLite PRAGMAs (journal_mode, foreign_keys, busy_timeout, synchronous, cache mode, and more) are configurable as URL query parameters on the connection string.
  • Custom SQL functions and hooks - RegisterFunc, RegisterAggregator, and RegisterCollation let Go functions run inside SQLite queries; commit, rollback, update, authorizer, and pre-update hooks expose transaction-level callbacks.
  • Build-tag-gated extensions - opt into FTS5 full-text search, JSON functions, ICU, virtual tables, user authentication, serialization, math functions, and more, each without bloating the default build.
  • Continuous fuzz testing - a dedicated CIFuzz GitHub Actions workflow fuzz-tests the CGO binding surface alongside the standard cross-platform test matrix.

Common Use Cases

  • Embedded application storage - desktop, CLI, and single-binary Go services that need a durable local database without running a separate database server.
  • Testing and local development - swapping in an in-memory or file-based SQLite database (:memory: or file::memory:?cache=shared) to run the same database/sql code paths without a Postgres/MySQL instance.
  • Edge and embedded devices - resource-constrained environments (IoT, edge compute) where a full client-server database is impractical but SQL semantics are still wanted.
  • Full-text search on local data - enabling the sqlite_fts5 build tag to index and query local text data without standing up a separate search engine.
  • Custom SQL logic via Go functions - registering domain-specific Go functions (e.g. regex matching, custom aggregates) as callable SQL functions inside queries.

Under The Hood

Architecture

The package centers on sqlite3.go, which implements database/sql/driver.Driver via SQLiteDriver.Open, returning a SQLiteConn that wraps a C.sqlite3 handle and implements Exec, Query, Prepare, and Begin. CGO callback plumbing (custom functions, aggregates, hooks) lives in callback.go, using an internal handle-lookup table rather than passing Go pointers directly to C, satisfying Go’s cgo pointer-passing rules; each exported trampoline (callbackTrampoline, stepTrampoline, commitHookTrampoline, updateHookTrampoline, preUpdateHookTrampoline) resolves back to a registered Go closure. Optional SQLite compile-time features are each isolated in their own sqlite3_opt_.go file, gated by Go build tags that map directly to the corresponding C preprocessor macros, keeping the default build’s C surface area minimal while still allowing consumers to opt into fts5, icu, json, dbstat, vtable, userauth, and similar extensions individually.

Tech Stack

Written in Go 1.21+ with zero external Go module dependencies (go.mod declares none beyond the standard library) and CGO_ENABLED=1 plus a working gcc toolchain as the only build requirement. Rather than linking a system libsqlite3, the package vendors an amalgamated SQLite3 C source (sqlite3-binding.c/h, prefixed to avoid gccgo build collisions) that’s compiled directly into the consuming binary; the libsqlite3 build tag switches to linking the system library instead. GitHub Actions CI (go.yaml) exercises the driver across platforms and Go versions, with dedicated workflows for releases (release.yaml), Docker-based verification (docker.yaml), and continuous fuzzing (cifuzz.yaml).

Code Quality

Twenty _test.go files cover the core driver alongside dedicated tests for backups, callbacks, crypt functions, extension loading, and nearly every optional build-tag feature individually (fts3, math functions, dbstat, preupdate hooks, serialize, unlock notify, vtable, userauth), mirroring the codebase’s per-feature file layout. Errors are surfaced as typed Error, ErrNo, and ErrNoExtended values rather than opaque strings, so callers can pattern-match on specific SQLite result and extended-result codes (e.g. ErrConstraintUnique, ErrBusy) instead of parsing error text. A continuous fuzzing workflow targeting the CGO binding surface is unusually rigorous for a driver package, and Go doc comments are present throughout the exported API.

API Design The package’s core technical choice is a hand-rolled, self-contained CGO bridge to a vendored SQLite amalgamation, avoiding both a system libsqlite3 runtime dependency and the overhead of shelling out to the sqlite3 CLI, while still supporting an opt-in system-library link mode. It implements the full database/sql/driver contract plus SQLite-specific extensions (custom functions, aggregates, collations, and transaction hooks) so Go code can reach into SQLite’s C extension API without writing any C itself. Optional compile-time SQLite features map cleanly onto Go build tags on a one-feature-per-file basis, and dozens of SQLite PRAGMAs are exposed as ordinary DSN query parameters, keeping the standard library’s sql.Open idiom intact while still surfacing engine-specific tuning knobs.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers