Remote SQLite with quicSQL
LiteORM’s SQLite backend runs a database in-process — pure Go, no C toolchain, via the sibling gosqlite.org. The same backend can also talk to a remote SQLite server, quicSQL, over the network: the same models, the same query and orm API, the same normalized errors. Only the DSN changes.
Connecting
Section titled “Connecting”sqlite.Open dispatches on the DSN’s shape. A bare path (app.db, :memory:) or a file: URI opens in-process; a URL-scheme DSN whose scheme is not file opens a remote quicSQL server. Blank-import the driver once so the quicsql:// scheme is registered:
import ( _ "quicsql.net/client/sqldriver" // registers the quicsql:// scheme "liteorm.org/dialect/sqlite" "liteorm.org/orm")
db, err := sqlite.Open("quicsql://host:7777/app?transport=h2&token=…")if err != nil { return err}defer db.Close()
// From here it's the ordinary SQLite backend — remote is invisible to your code._ = orm.AutoMigrateAll(ctx, db, User{}, Post{})orm.AutoMigrateAll, the orm.Repo, the query builder, transactions (with SAVEPOINT-nested Begin), schema introspection, and migrations all run as SQL on the server, and SQLite constraint violations normalize to the same liteorm.ErrUniqueViolation / ErrForeignKey / … sentinels you get locally.
Credentials require TLS. A token (or any credential) rides in the DSN, so use a verified TLS transport — transport=h2 or h3. The driver fails closed: it refuses to connect when a credential would ride an unverified or plaintext channel (insecure=1, transport=h2c, or the h1 default) rather than send the token in the clear.
mTLS and keyring auth: WrapDB
Section titled “mTLS and keyring auth: WrapDB”A DSN can’t carry an mTLS client certificate or an ed25519 keyring. For those, build the *sql.DB yourself with the quicSQL client and adapt it with sqlite.WrapDB — the same seam Open uses internally:
// qc is a *client.Client from quicsql.net/client, configured with your mTLS// certificate or keyring; sqldriver turns it into a database/sql connector.db := sqlite.WrapDB(sql.OpenDB(sqldriver.OpenConnectorClient(qc)))Open with a quicsql:// DSN is just WrapDB over sql.Open("sqlite", dsn), so reach for WrapDB only when you built the connection yourself. sqlite.RawDB(sess) returns the underlying *sql.DB of a remote session if you need the driver handle directly.
What works over the wire
Section titled “What works over the wire”The SQLite subpackages run against a remote server, not just a local file:
| Feature | Remote behavior |
|---|---|
| Search — vector / FTS5 / hybrid | runs as SQL against the vec0/fts5 sidecars on the server (the server must have vec0 registered; fts5 is built in) |
| Changesets — Capture / Apply / Invert / Concat | drives the SESSION extension server-side |
| Large objects | transfer whole — WriteFrom / ReadAll / Size / Drop |
The one local-only remainder is the streaming large-object handle (lob.Open / Read / Truncate, which return native io.WriterAt / io.ReaderAt) — over the wire, large objects move whole. Use a local database (Open / OpenEncrypted / a vault) when you need streaming or partial blob I/O.
Where quicSQL fits
Section titled “Where quicSQL fits”Together with the in-process backend, LiteORM’s SQLite dialect spans both ends: an embedded, CGo-free database for a single process, and a shared, networked server for many — reached through one API. Postgres, MySQL, and SQL Server remain first-class for when you want those engines.
See also
Section titled “See also”- Connecting to a database — opening every backend.
- Backends — the per-dialect capability matrix.
- API:
liteorm.org/dialect/sqlite—Open,WrapDB,RawDB.