Skip to Content

Databases

We ran each driver against a real server in Docker (Postgres 16, MySQL 8.4, Redis 7) and compared the result with Node 24.

Driver3va 2.9.0 (Postgres rows re-measured on 2.12.1)Notes
ioredis 5.6✅ Works
node:sqlite (built-in)✅ WorksNeeds read/write grants on the .db file
pg 8.16, Client✅ Works (2.12.1)SCRAM-SHA-256 fixed; md5/trust always worked
pg 8.16, Pool✅ Works (2.12.1)Failed on 2.9.0/2.12.0 (stream.ref is not a function)
postgres (postgres.js) 3.4⚠️ Works (2.12.1)sql.end() never resolves
mysql2 3.14❌ Failsoffset is out of bounds
mysql 2.18❌ Fails (on Node too)This old driver doesn’t support MySQL 8’s default auth
better-sqlite3 12❌ FailsIts binary comes from a shell install script, which 3va refuses even when allowlisted
drizzle-orm + pg❔ Not re-measuredUses pg.Pool, which works in 2.12.1

Permissions

A database client needs a network grant for the database host, plus env access for the connection string:

3va run app.js --allow-read=./node_modules --allow-net=db.internal --allow-env=DATABASE_URL

A bare host allows every port; --allow-net=db.internal:5432 limits the driver to that port. Raw TCP connections check host:port the same way fetch does.

For SQLite, grant the database file (and its -wal/-shm siblings if you use WAL mode):

3va run app.js --allow-read=./app.db --allow-write=./app.db

Postgres

Measured on 3va 2.12.1 against Postgres 16 (SCRAM-SHA-256, the default), with pg and postgres from npm:

DriverResult on 2.12.1
pg, Client✅ Connects with SCRAM and queries
pg, Pool✅ Reusing connections works (3 queries in a row)
postgres (postgres.js)✅ Connects with SCRAM and queries; ⚠️ await sql.end() never resolves, so call process.exit() when you are done

Earlier versions failed here. On 2.9.0, SCRAM broke with importKey: unsupported format/algorithm: raw/PBKDF2 (pg) or SASL_SIGNATURE_MISMATCH (postgres.js), because crypto.pbkdf2Sync(...), createHash().digest() and createHmac().digest() returned a bare Uint8Array whose .toString("hex") is a comma-separated list. And pg.Pool threw this.stream.ref is not a function on its first query. Both are fixed in 2.12.1 (importKey("raw") for PBKDF2/HMAC worked from 2.12.0). On older versions use a Client against a server with md5 auth, or stay on Node.

MySQL

mysql2 connects but fails on the first query with offset is out of bounds (a Buffer issue). The older mysql package fails on MySQL 8’s default auth on Node too, so it’s no alternative.

SQLite

Use the built-in node:sqlite:

const { DatabaseSync } = require("node:sqlite"); const db = new DatabaseSync("./app.db"); db.exec("create table if not exists items(id integer primary key, name text)"); db.prepare("insert into items(name) values(?)").run("from 3va");

better-sqlite3, sqlite3 and other native drivers download or compile their binary in an install script. Even with "onlyBuiltDependencies": ["better-sqlite3"], 3va refuses that script because it’s a shell command (prebuild-install || node-gyp rebuild), so the binary is missing.

ORMs

  • Drizzle with node-postgres hangs because of the pg.Pool bug.
  • Prisma wasn’t tested. It relies on a native query engine downloaded at install time and on child processes, so expect the same problem as better-sqlite3.