An exploration of three ways to embed SQLite queries into Nix evaluation, since Nix's builtins.fromJSON eagerly parses entire files and can't do partial lookups. The author tests builtins.exec (fork/exec into sqlite3 CLI, parsing stdout as Nix syntax), builtins.importNative (dlopen a shared object with cached SQLite handles), and Determinate Systems' new builtins.wasm (running a WASM-compiled SQLite with a custom VFS reading raw byte ranges via a patched read_file_range API). Benchmarks show fromJSON is a flat 0.29s regardless of query count, builtins.exec starts cheap but scales linearly (~3.8ms/query), importNative is fast and flat (~0.05s) due to warm handles, and the wasm SQLite pays a ~2.5s Cranelift JIT cost upfront then ~7ms per query. For the nixpkgs-multiverse project's current index size, plain JSON still wins, and the author avoids shipping anything requiring unsafe native code.

13m read timeFrom fzakaria.com
Post cover image
Table of contents
§ One lookup costs the whole file§ One: builtins.exec§ Two: builtins.importNative§ Three: builtins.wasm§ Can I haz SQLite?§ Benchmark§ What I actually want

Questions this post answers

What is builtins.wasm in Nix and when was it added?

builtins.wasm is a Nix builtin that calls a function inside a WebAssembly module, shipped by Determinate Systems in March 2026. It requires the wasm-builtin experimental feature and Determinate Systems' patched Nix build. Unlike builtins.exec or builtins.importNative, WASM execution is sandboxed and deterministic, intended as a safe escape hatch for extending Nix without expanding core builtins. Developers tracking new Nix evaluator capabilities like this can follow the ecosystem's evolution on daily.dev.

Why can't I read a binary file like a SQLite database with Nix's builtins.readFile?

Nix strings cannot contain NULL bytes, so builtins.readFile fails on binary files such as a SQLite database, throwing an error that the file contents cannot be represented as a Nix string. A separate WASM host function called read_file exists to pull raw bytes into WASM memory, though it still reads the entire file rather than allowing partial reads. Anyone debugging binary-file quirks in Nix evaluation can dig into workarounds like this on daily.dev.

How does querying SQLite with builtins.exec in Nix compare in performance to builtins.importNative?

builtins.exec starts cheaper per call but scales linearly at roughly 3.8ms per query because each call forks, execs the sqlite3 binary, and re-parses its stdout as Nix syntax, crossing fromJSON's fixed 0.29s cost around eighty queries. builtins.importNative stays flat at about 0.05s across any number of queries because it caches the SQLite handle and keeps b-tree pages warm across the whole evaluation. Engineers weighing Nix builtin tradeoffs for database-backed evaluation can compare approaches like this on daily.dev.

1.3K Impressions