A database engine that's
3-10x faster than SQLite

From-scratch Rust database with PowQL -- a pipeline query language that reads left to right -- plus a SQL frontend on the same engine. One engine, two languages. Compiled predicates. Pure-Rust core. Built for single-writer embedded state and read-only snapshot serving, not for many clients sharing one read-write database.

$ cargo install powdb-cli

Where PowDB fits

PowDB is a single-writer embedded engine with truly parallel reads. Every writer takes the whole write-admission gate, and there is no MVCC. That shape decides where it shines.

Reach for PowDB when
  • Single-writer embedded app state in Rust or Node (in-process, typed results, injection-inert params)
  • Local agent or tool memory: local-first, single-process, refreshed by swapping in a new snapshot in seconds
  • Read-only edge snapshot serving from N processes, with no write gate at all
  • Per-tenant, process-isolated databases (one writer per tenant)
  • Fast, disposable CI and test databases
  • Bulk ingest feeding read-heavy internal tools and dashboards
Use something else when
  • Many concurrent clients share one read-write database -- that is Postgres's home turf; PowDB serializes writers through one gate, so shared read-write concurrency amplifies read latency
  • You need live replication or sync across nodes -- reach for Turso
  • Your workload is analytical column-crunching over one big dataset -- reach for DuckDB

Benchmarks

PowDB vs SQLite on 100K rows (M1), both engines in memory-mode, real numbers, no cherry-picking. These are single-request latencies (one query at a time), not throughput under many simultaneous clients. Single-row durable inserts are fsync-bound; that write story is covered in Embedded in Node below.

Workload PowDB SQLite Speedup
agg_min 236µs 2.34ms 9.9x
agg_max 236µs 2.10ms 8.9x
agg_sum 231µs 1.87ms 8.1x
update_by_pk 55ns 412ns 7.5x
agg_avg 401µs 2.30ms 5.7x
scan_filter_count 381µs 1.95ms 5.1x
scan_filter_sort_limit 2.66ms 9.77ms 3.7x
update_by_filter 2.16ms 6.77ms 3.1x
point_lookup_indexed 93ns 282ns 3.0x
multi_col_and_filter 2.22ms 4.70ms 2.1x
insert_batch_1k 238ns 320ns 1.3x
delete_by_filter 1.76ms 2.35ms 1.3x
scan_filter_project_top100 9.6µs 12.7µs 1.3x
point_lookup_nonindexed 350µs 432µs 1.2x

PowQL vs SQL

PowQL reads left to right like a pipeline. No SELECT ... FROM ... WHERE juggling.

Filter and project

SQL
SELECT name, price
FROM Product
WHERE price > 10
ORDER BY name;
PowQL
Product filter .price > 10
order .name
{ .name, .price }

Aggregate with filter

SQL
SELECT AVG(age)
FROM User
WHERE city = 'NYC';
PowQL
avg(User filter .city = "NYC"
{ .age })

Group by with having

SQL
SELECT status, COUNT(*)
FROM User
GROUP BY status
HAVING COUNT(*) > 5;
PowQL
User group .status
having count(*) > 5
{ .status, count(*) }

Insert a row

SQL
INSERT INTO User (name, email, age)
VALUES ('Alice', 'alice@example.com', 30);
PowQL
insert User {
  name := "Alice",
  email := "alice@example.com",
  age := 30
}

Embedded in Node — no server

The same engine, in-process. @zvndev/powdb-embedded is a native Node addon: open a database, run PowQL or SQL, no TCP, no daemon. It beats SQLite on writes once you pick a durability mode.

$ npm install @zvndev/powdb-embedded
index.mjs
import { Database } from "@zvndev/powdb-embedded";

const db = Database.open("./data");

// "normal" = off-lock background fsync: much faster writes,
// a bounded crash-loss window. This closes the write gap vs SQLite.
db.setSyncMode("normal");

db.query('type User { required name: str, required email: str, age: int }');
db.query('insert User { name := "Alice", email := "alice@example.com", age := 30 }');

// PowQL
db.query('User filter .age > 25 { .name, .age }');

// ...or SQL, on the same handle — lowered to PowQL by the SQL frontend
db.querySql("SELECT name, age FROM User WHERE age > 25 ORDER BY age DESC");

Durability is a knob, not a fork: "full" fsyncs every commit (safest, the default), "normal" moves the fsync off the write lock for a bounded crash-loss window, and batching writes in a begin/commit transaction collapses a whole bulk load into a single fsync. That is how single-row insert throughput stops being fsync-bound.

Built for Performance

Every layer of PowDB is written in Rust, from the storage engine to the query executor.

Compiled Predicates

Filter expressions compile into byte-level operations that skip full row decoding. This is why aggregate and scan workloads run up to 10x faster than SQLite.

B+ Tree Indexes

Disk-persisted B+ tree indexes in a custom BIDX binary format. Indexed point lookups resolve in under 100ns. Indexes survive restarts and are used automatically.

WAL + Crash Recovery

Write-ahead log with statement-boundary group commit. Full crash recovery via WAL replay, page-zero recovery, and automatic index rebuild.

Plan Cache

FNV-1a hashed plan cache with literal substitution. Parse and plan once, execute thousands of times. Prepared queries skip the entire front-end pipeline.

SQL Frontend

A SQL parser lowers a supported subset — SELECT/JOIN/GROUP BY, INSERT ... RETURNING, AUTOINCREMENT, DDL, transactions — to the same PowQL AST and plan cache. One engine, two languages, no second execution path.

Embedded in Node

Native in-process addon (@zvndev/powdb-embedded): Database.open, then PowQL or SQL with no server. setSyncMode("normal") is what beats SQLite on writes.

TypeScript Client

First-class TypeScript client (@zvndev/powdb-client) with a clean async API. Connect to PowDB server over TCP with full type safety.

TLS + Authentication

TLS encryption plus two auth modes: a shared password (POWDB_PASSWORD) or named users with roles (admin / readwrite / readonly, argon2id-hashed).

Zero C Dependencies

Pure Rust, end to end. No C FFI, no libsqlite3-sys, no bindgen. Single cargo install on any platform Rust supports.

Pipeline Query Language

PowQL reads left to right: table, filter, order, limit, project. No inside-out clause structure. Queries read like sentences.

When PowDB is not the right fit

PowDB is pre-1.0 and deliberately scoped. Be honest with yourself before adopting it:

If any of those are dealbreakers, use SQLite -- and we say so plainly in PowDB vs SQLite: when to use which.