| name | pgmicro-postgres-sqlite |
| description | Use pgmicro — an in-process PostgreSQL reimplementation backed by SQLite-compatible storage, embeddable as a library or CLI |
| triggers | ["use pgmicro in my project","embed postgres in my app","in-process postgresql database","pgmicro setup and usage","sqlite backed postgres","run postgresql without a server","pgmicro javascript sdk","embeddable postgres database rust"] |
pgmicro
Skill by ara.so — Daily 2026 Skills collection.
pgmicro is an in-process reimplementation of PostgreSQL backed by a SQLite-compatible storage engine. It parses PostgreSQL SQL using the real PostgreSQL parser (libpg_query) and compiles it directly to SQLite VDBE bytecode, executed by Turso. The result is a fast, embeddable, single-file (or in-memory) database that speaks PostgreSQL — no server process required.
Key capabilities
- Full PostgreSQL SQL syntax (via the actual PG parser)
- SQLite-compatible
.db file format (readable by any SQLite tool)
- JavaScript/TypeScript SDK (WASM-based, runs in Node.js and browsers)
- PostgreSQL wire protocol server mode (connect with
psql, ORMs, etc.)
- Dialect switching: access the same database with PG or SQLite syntax
- PostgreSQL system catalog virtual tables (
pg_class, pg_attribute, pg_type, etc.)
Installation
CLI (Node.js)
npx pg-micro
npm install -g pg-micro
pg-micro myapp.db
JavaScript/TypeScript SDK
npm install pg-micro
From source (Rust)
git clone https://github.com/glommer/pgmicro
cd pgmicro
cargo build --release
./target/release/pgmicro
CLI usage
pgmicro
pgmicro myapp.db
pgmicro myapp.db --server 127.0.0.1:5432
pgmicro :memory: --server 127.0.0.1:5432
CLI meta-commands
\? Show help
\q Quit
\dt List tables
\d <table> Describe table schema
JavaScript/TypeScript SDK
Basic usage
import { connect } from "pg-micro";
const db = await connect(":memory:");
const db = await connect("./myapp.db");
await db.exec(`
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
`);
await db.exec(`
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')
`);
const stmt = await db.prepare("SELECT * FROM users WHERE name = ?");
const rows = await stmt.all("Alice");
console.log(rows);
const row = await stmt.get("Alice");
await db.exec("INSERT INTO users (name, email) VALUES (?, ?)", ["Bob", "bob@example.com"]);
await db.close();
Parameterized queries
import { connect } from "pg-micro";
const db = await connect(":memory:");
await db.exec(`
CREATE TABLE events (
id SERIAL PRIMARY KEY,
type TEXT NOT NULL,
payload TEXT,
ts TEXT DEFAULT CURRENT_TIMESTAMP
)
`);
const insert = await db.prepare(
"INSERT INTO events (type, payload) VALUES ($1, $2)"
);
await insert.run("user.signup", JSON.stringify({ userId: 42 }));
await insert.run("page.view", JSON.stringify({ path: "/home" }));
const query = await db.prepare(
"SELECT * FROM events WHERE type = $1 ORDER BY id DESC"
);
const signups = await query.all("user.signup");
console.log(signups);
await db.close();
Transactions
import { connect } from "pg-micro";
const db = await connect(":memory:");
await db.exec("CREATE TABLE accounts (id INT PRIMARY KEY, balance INT)");
await db.exec("INSERT INTO accounts VALUES (1, 1000), (2, 500)");
await db.exec("BEGIN");
try {
await db.exec("UPDATE accounts SET balance = balance - 100 WHERE id = 1");
await db.exec("UPDATE accounts SET balance = balance + 100 WHERE id = 2");
await db.exec("COMMIT");
} catch (err) {
await db.exec("ROLLBACK");
throw err;
}
const rows = await db.prepare("SELECT * FROM accounts").all();
console.log(rows);
await db.close();
Using with TypeScript types
import { connect } from "pg-micro";
interface User {
id: number;
name: string;
email: string;
created_at: string;
}
const db = await connect(":memory:");
await db.exec(`
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
`);
await db.exec("INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')");
const stmt = db.prepare<User>("SELECT * FROM users");
const users: User[] = await stmt.all();
console.log(users[0].name);
await db.close();
PostgreSQL features supported
CREATE TABLE items (id SERIAL PRIMARY KEY, name TEXT);
CREATE FUNCTION hello() RETURNS TEXT AS $$
SELECT 'hello world';
$$ LANGUAGE SQL;
SELECT '42'::int;
SELECT NOW()::text;
SELECT data->>'key' FROM records;
CREATE TABLE typed (
n INT,
f FLOAT8,
t TEXT,
b BOOLEAN,
ts TIMESTAMP,
j JSON
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
total NUMERIC NOT NULL CHECK (total >= 0),
state TEXT DEFAULT 'pending'
);
Server mode with psql / ORMs
pgmicro myapp.db --server 127.0.0.1:5432
psql -h 127.0.0.1 -p 5432 -U turso -d main
import { Client } from "pg";
const client = new Client({
host: "127.0.0.1",
port: 5432,
user: "turso",
database: "main",
});
await client.connect();
const res = await client.query("SELECT * FROM users");
console.log(res.rows);
await client.end();
Architecture overview
PostgreSQL SQL → libpg_query (real PG parser) → PG parse tree
│
Translator (parser_pg/)
│ Turso AST
Turso Compiler
│ VDBE bytecode
Bytecode Engine (vdbe/)
│
SQLite B-tree storage (.db file)
- The
.db output file is a standard SQLite database — open it with DB Browser for SQLite, the sqlite3 CLI, or any SQLite library.
- PostgreSQL system catalog tables (
pg_class, pg_attribute, pg_type, pg_namespace) are exposed as virtual tables so psql meta-commands like \dt and \d work correctly.
Common patterns
Per-request ephemeral databases (AI agents, sandboxes)
import { connect } from "pg-micro";
async function runAgentSession(agentId: string, sql: string) {
const db = await connect(":memory:");
await db.exec("CREATE TABLE scratch (key TEXT PRIMARY KEY, value TEXT)");
await db.exec(
"INSERT INTO scratch VALUES ($1, $2)",
[`agent-${agentId}`, sql]
);
const result = await db.prepare("SELECT * FROM scratch").all();
await db.close();
return result;
}
Inspecting the SQLite file directly
sqlite3 myapp.db ".tables"
sqlite3 myapp.db "SELECT * FROM users"
sqlite3 myapp.db ".schema users"
Schema introspection via pg catalog
SELECT tablename FROM pg_tables WHERE schemaname = 'public';
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'users';
Troubleshooting
SERIAL column not auto-incrementing
Ensure you are not explicitly inserting NULL into the id column — insert without the column name and pgmicro will auto-assign.
psql meta-commands (\dt, \d) show nothing
Make sure you created tables in the public schema (the default). The PostgreSQL catalog virtual tables are populated from actual schema metadata.
File database not persisting
Pass a real file path, not :memory:. Confirm the process has write permission to the target directory.
Wire protocol server refused by client
The server supports a subset of the PostgreSQL wire protocol. Some advanced client features (SSL, SCRAM auth, extended query protocol edge cases) may not be implemented yet. Use simple query mode when possible.
Unsupported PostgreSQL syntax
pgmicro is experimental — not all PostgreSQL features are translated. Check the translator layer (parser_pg/) for what is currently mapped. Common gaps: stored procedures with complex PL/pgSQL, window functions, CTEs (may be partial), COPY command.
Build errors from source
Ensure you have a recent stable Rust toolchain (rustup update stable) and that libpg_query native dependencies (C compiler, cmake) are available on your system.
Resources