zombiezen go-sqlite: a SQLite binding for Go that skips database/sql
Low-level Go interface to SQLite 3
At a glance
- What is it?
- zombiezen.com/go/sqlite is a fork of crawshaw.io/sqlite that runs SQLite through the CGo free modernc.org/sqlite translation and deliberately does not implement a database/sql driver. That choice is the whole design, and it buys SQLite specific features that the standard database interface hides.
- Who is it for?
- zombiezen.com/go/sqlite fits Go engineers who want direct access to SQLite, who need blob I/O or user defined functions, or who need a build with CGO_ENABLED=0 for cross compilation and the race detector. It does not fit teams who want a database/sql driver, because the project deliberately does not provide one and points you at modernc.org/sqlite instead.
- Can I use it commercially?
- Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 114 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 6, 2026, and from our analysis. They are not legal advice.
Star history
- zombiezen/go-sqlite982 ★ · +1
| Repository | 2026-10-21 | 2026-11-06 |
|---|---|---|
| zombiezen/go-sqlite | 981 | 982 |
1 Stars in the last 16 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
A fork that refuses to implement database/sql
zombiezen.com/go/sqlite provides a low-level Go interface to SQLite 3. It is a fork of crawshaw.io/sqlite that swaps the CGo backed engine for modernc.org/sqlite, a CGo free SQLite package, and it aims to be a mostly drop-in replacement for crawshaw.io/sqlite.
The interesting decision comes next, and it is stated bluntly: this package deliberately does not provide a database/sql driver. The README points to David Crawshaw's own write up for the reasoning, and gives the practical alternative in one sentence. If you want to use database/sql with SQLite without CGo, use modernc.org/sqlite directly.
That is a real architectural stance rather than an omission. A database/sql driver presents a fixed interface, and SQLite is full of behaviour that interface cannot express: incremental blob I/O, user defined functions registered per connection, virtual tables, session extensions, custom collations. If you need those, you are handed a low-level API where they exist, and if you do not need them, the README is effectively telling you to pick a different package.
The audience is therefore Go developers writing applications where SQLite is the storage engine and the shape of the data matters, rather than teams that just want a familiar sql.DB handle. The licence is ISC, the homepage is the pkg.go.dev page for the module, and the topic tags are database, golang, golang-library, golang-package, sqlite and sqlite3.
Full SQLite, translated from C into Go
Underneath, the engine is not a reimplementation of SQLite but a translation of it. The README describes modernc.org/sqlite as an automatically generated translation of the original C source code of SQLite into Go, which is what makes full SQLite functionality available through this package.
That design has two consequences that matter in practice.
The first is the build. The package builds with CGO_ENABLED=0, and the README lists the two things that buys: cross compiling, and data race detection. Cross compiling matters for anyone shipping a binary for another architecture, and the race detector matters because the Go runtime race detector is only available in CGo enabled builds by default, so a pure Go SQLite means you can run your tests under the race detector without giving up the library.
The second consequence is that this is not a thin wrapper. You get the real SQLite engine, with the same file format, the same SQL dialect and the same extensions, running as Go code. The cost of that translation is binary size and, in exchange, the absence of a C toolchain and the absence of CGo in your build pipeline.
The dependency list in go.mod shows what that means concretely. The module requires modernc.org/sqlite v1.37.1 and modernc.org/libc v1.65.7, which is the portability layer the translation relies on, plus crawshaw.io/iox for the original I/O abstractions, github.com/chzyer/readline for the interactive shell, golang.org/x/text for text handling, and github.com/google/go-cmp for tests.
One detail in the manifest is worth noting. Two versions are retracted, v0.9.1 and v0.9.0, with the comment that v0.9.0 had libc memgrind issues. Retracted versions are excluded from normal module resolution, so a project pinned to one of those is in a bad spot and should move.
Opening a connection and running your first query
Installing the package is a single go get, and the README adds a caution right after it: while the library does not use CGo, make sure that you are building for one of the supported architectures listed for modernc.org/sqlite.
go get zombiezen.com/go/sqliteThe getting started example opens an in-memory database and prints a value from a query. The imports are the two packages you need for the pattern, the core binding and the sqlitex helper package:
import (
"fmt"
"zombiezen.com/go/sqlite"
"zombiezen.com/go/sqlite/sqlitex"
)The connection is opened with an explicit open flag, and the handle is closed with a defer:
conn, err := sqlite.OpenConn(":memory:", sqlite.OpenReadWrite)
if err != nil {
return err
}
defer conn.Close()The query runs through sqlitex.ExecuteTransient, with a result callback that reads the first column as text:
err = sqlitex.ExecuteTransient(conn, "SELECT 'hello, world';", &sqlitex.ExecOptions{
ResultFunc: func(stmt *sqlite.Stmt) error {
fmt.Println(stmt.ColumnText(0))
return nil
},
})The word transient is doing the work here. The statement is prepared, run and finalised as part of the call, so there is no prepared statement handle to manage for a one shot query. For a query you intend to run repeatedly, the lower level statement API is the path, and the reference documentation on pkg.go.dev covers the package examples.
If you are starting a new application, the README points to those package examples. If you are moving existing code that uses crawshaw.io/sqlite, it points to the migration docs instead, which is the topic of a section further down.
The helper packages: sqlitex, sqlitemigration, sqlitefile and a REPL
The repository root is mostly the binding itself, with the file names giving the API surface away: auth.go, backup.go, blob.go, blocking_step.go, func.go, op_type.go, openflags.go, result.go, session.go, vtable.go and sqlite.go. That is a fairly complete picture of what a low-level SQLite binding exposes, from authorization callbacks through backup and sessions to virtual tables.
Around that core sit four subpackages, each solving a problem that would otherwise be your own code.
sqlitex holds the execution helpers used in the getting started snippet, and it also provides ExecScriptFS, a utility for running embedded SQL scripts using the Go 1.16 embedding feature. That means a migration script can live in your repository as a .sql file, embedded in the binary, and run at startup without shipping loose files.
sqlitemigration is the schema migration package, and the README calls it simple. It is the piece that makes the embedded script approach work as a migration system rather than as one off setup code.
sqlitefile handles the database file itself, and there is a separate shell/ directory holding the simple REPL for debugging, which is the package the go.mod readline dependency exists for.
There is also a cmd/ directory holding the migration tool, and an ext/ directory for extensions. The repository carries a flake.nix, a go.work file and a CHANGELOG.md, plus .envrc, which tells you this project is developed with a Nix toolchain and a Go workspace, and that releases are tracked in a changelog rather than only in git tags.
Blob I/O, user defined functions and the go fix style migration tool
The features list is where the design choice pays off. The README calls out the ability to access SQLite specific features like blob I/O and user defined functions, and those are precisely the things a database/sql driver cannot offer.
Blob I/O means incremental reading and writing of a BLOB value rather than materialising the whole thing in memory, which is the difference between a workable and an unusable path for images or large payloads stored inside SQLite. User defined functions means you can register a Go function as a SQL callable, with Conn.CreateFunction named in the README as the entry point, and that registration is per connection, which is why a low-level API that owns connections matters.
There is a third feature worth pulling out, because it saves an afternoon: a go fix-like tool for migrating existing code that uses crawshaw.io/sqlite. The README links the migration docs at cmd/zombiezen-sqlite-migrate/README.md. Since this package aims to be a mostly drop-in replacement for crawshaw.io/sqlite, an automated rewriter is what makes that claim usable in practice, rather than something you discover one import path at a time.
The combination of these three is what tells you when to choose this package. If you need only prepared statements and rows, a database/sql driver is simpler and you should follow the README's own advice and use modernc.org/sqlite. If you need blobs, custom SQL functions or per connection state, this is the package that still exposes them.
ISC licence, Go version floor and where the releases stand
The licence is ISC, which is short and permissive, and the README points at the LICENSE file. For a database binding that is the right shape, since you are unlikely to want a copyleft obligation attached to your storage layer.
The Go version requirement is visible in go.mod. The module declares go 1.23.0 with a toolchain directive of go1.24.2, so a project adopting this needs a recent toolchain, and the toolchain directive means Go will fetch a newer toolchain automatically if the local one is older.
Release cadence is slow but the project is not abandoned. The tagged releases are v1.4.2 and v1.4.1, both from 2025-05-23, and v1.4.0 from 2024-09-23. The last push was on 2026-07-17, so changes are still landing on the main branch even though a new tag has not appeared in a while.
That gap between commits and tags is the practical thing to plan for. If you depend on this package, pin a released version rather than tracking main, and read the CHANGELOG.md in the repository before upgrading, because the SQLite engine underneath is a moving target and the Go API can change with it. The two retracted versions in go.mod are a reminder that this dependency's history contains the occasional sharp edge.
Editorial conclusion
zombiezen.com/go/sqlite fits Go engineers who want direct access to SQLite, who need blob I/O or user defined functions, or who need a build with CGO_ENABLED=0 for cross compilation and the race detector. It does not fit teams who want a database/sql driver, because the project deliberately does not provide one and points you at modernc.org/sqlite instead. Verify first that your target platform is on the supported architectures list of modernc.org/sqlite, that your Go toolchain satisfies the module's go 1.23.0 directive, and that the sqlitex and sqlitemigration packages cover the helpers you were planning to write yourself.
Frequently asked questions
Does zombiezen.com/go/sqlite provide a database/sql driver?
No, and that is deliberate. The README says the package does not provide a database/sql driver and points to David Crawshaw's rationale, recommending modernc.org/sqlite directly if you want database/sql with SQLite without CGo.
How do I install zombiezen.com/go/sqlite?
Run go get zombiezen.com/go/sqlite. Even though the library does not use CGo, the README says to make sure you are building for one of the supported architectures listed for modernc.org/sqlite.
Can I use blob I/O and user defined functions with this SQLite package?
Yes. The README lists access to SQLite specific features such as blob I/O and user defined functions, with Conn.CreateFunction as the documented entry point for registering a Go function with SQLite.
How do I move existing code from crawshaw.io/sqlite to zombiezen.com/go/sqlite?
The README links migration docs for a go fix-like tool that rewrites code using crawshaw.io/sqlite, located at cmd/zombiezen-sqlite-migrate/README.md in the repository.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zombiezen-go-sqlite)Star history chart for your README
[](https://hysenlabs.com/projects/zombiezen-go-sqlite)Was this useful?