--- 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](https://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](https://github.com/tursodatabase/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) ```bash # Run without installing npx pg-micro # Install globally npm install -g pg-micro pg-micro myapp.db ``` ### JavaScript/TypeScript SDK ```bash npm install pg-micro ``` ### From source (Rust) ```bash git clone https://github.com/glommer/pgmicro cd pgmicro cargo build --release ./target/release/pgmicro ``` ## CLI usage ```bash # In-memory database (ephemeral) pgmicro # File-backed database pgmicro myapp.db # PostgreSQL wire protocol server pgmicro myapp.db --server 127.0.0.1:5432 # In-memory server (useful for testing) pgmicro :memory: --server 127.0.0.1:5432 ``` ### CLI meta-commands ``` \? Show help \q Quit \dt List tables \d Describe table schema ``` ## JavaScript/TypeScript SDK ### Basic usage ```typescript import { connect } from "pg-micro"; // In-memory database const db = await connect(":memory:"); // File-backed database const db = await connect("./myapp.db"); // DDL await db.exec(` CREATE TABLE users ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE, created_at TEXT DEFAULT CURRENT_TIMESTAMP ) `); // Insert await db.exec(` INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com') `); // Prepared statement — fetch all rows const stmt = await db.prepare("SELECT * FROM users WHERE name = ?"); const rows = await stmt.all("Alice"); console.log(rows); // [{ id: 1, name: 'Alice', email: 'alice@example.com', created_at: '...' }] // Fetch single row const row = await stmt.get("Alice"); // Execute with bound parameters await db.exec("INSERT INTO users (name, email) VALUES (?, ?)", ["Bob", "bob@example.com"]); await db.close(); ``` ### Parameterized queries ```typescript 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 ) `); // Positional parameters 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" })); // Query with filter 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 ```typescript 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)"); // Manual transaction 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); // [{ id: 1, balance: 900 }, { id: 2, balance: 600 }] await db.close(); ``` ### Using with TypeScript types ```typescript 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("SELECT * FROM users"); const users: User[] = await stmt.all(); console.log(users[0].name); // 'Alice' await db.close(); ``` ## PostgreSQL features supported ```sql -- SERIAL / auto-increment CREATE TABLE items (id SERIAL PRIMARY KEY, name TEXT); -- Dollar-quoted strings CREATE FUNCTION hello() RETURNS TEXT AS $$ SELECT 'hello world'; $$ LANGUAGE SQL; -- Cast syntax SELECT '42'::int; SELECT NOW()::text; -- JSON operators (where implemented) SELECT data->>'key' FROM records; -- Standard PG types CREATE TABLE typed ( n INT, f FLOAT8, t TEXT, b BOOLEAN, ts TIMESTAMP, j JSON ); -- PostgreSQL-style constraints CREATE TABLE orders ( id SERIAL PRIMARY KEY, total NUMERIC NOT NULL CHECK (total >= 0), state TEXT DEFAULT 'pending' ); ``` ## Server mode with psql / ORMs ```bash # Start server pgmicro myapp.db --server 127.0.0.1:5432 # Connect with psql psql -h 127.0.0.1 -p 5432 -U turso -d main # Connect with libpq connection string (Node.js pg driver) # DATABASE_URL=postgresql://turso@127.0.0.1:5432/main ``` ```typescript // Using node-postgres (pg) against pgmicro server 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) ```typescript import { connect } from "pg-micro"; async function runAgentSession(agentId: string, sql: string) { // Each session gets its own isolated in-memory DB — no cleanup needed const db = await connect(":memory:"); await db.exec("CREATE TABLE scratch (key TEXT PRIMARY KEY, value TEXT)"); // Agent writes intermediate results 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 ```bash # pgmicro writes standard SQLite — use sqlite3 CLI to inspect sqlite3 myapp.db ".tables" sqlite3 myapp.db "SELECT * FROM users" sqlite3 myapp.db ".schema users" ``` ### Schema introspection via pg catalog ```sql -- List all user tables SELECT tablename FROM pg_tables WHERE schemaname = 'public'; -- List columns for a table 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 - [GitHub: glommer/pgmicro](https://github.com/glommer/pgmicro) - [Turso (upstream engine)](https://github.com/tursodatabase/turso) - [libpg_query](https://github.com/pganalyze/libpg_query) — the PostgreSQL parser extraction library - [pg_query Rust crate](https://crates.io/crates/pg_query) - [npm: pg-micro](https://www.npmjs.com/package/pg-micro)