1. Start with an in-memory database for quick prototyping/tests
2. Switch to a local on-disk PGlite DB
3. Move to a real remote PostgreSQL instance
…all using the same API and code, with an optional local↔remote sync mode for offline-first apps.
Why?
Most apps go through these stages:
1. Prototyping/Testing – you just want a fast, zero-setup in-memory DB.
2. Local-first – you want offline capability but still sync to the cloud.
3. Production – you want a full PostgreSQL instance, without rewriting your data layer.
Ominipg is my attempt to make that path smoother.
Modes
- url: ":memory:" – PGlite in WASM, in-memory. Great for tests, demos, or quick spikes. No Postgres install required. - url: "path/to/db" – PGlite with disk storage. Nice for desktop apps, CLIs, or local development. - url: "postgresql://..." – Direct connection to your remote/production Postgres.
Local + Remote sync (both URLs) – Use a local PGlite DB that automatically syncs with remote Postgres, so you can build offline-first apps or just get faster reads while still persisting everything remotely.
Under the hood, PGlite runs in a Web Worker automatically (when available), so heavy queries don’t block your main thread – you don’t have to think about workers yourself.
Typed CRUD with Mongo-style queries
Instead of writing SQL, you can use MongoDB-style queries with TypeScript types inferred from JSON Schema definitions:
const adults = await db.crud.users.find({ age: { $gte: 18 }, status: { $in: ["active", "premium"] }, }); // `adults` is fully typed based on your `users` schema
If you prefer, you can also use Drizzle ORM on top, or drop down to raw SQL. Ominipg doesn’t force you into one style.
Example
import { Ominipg, defineSchema } from "jsr:@oxian/ominipg";
const schemas = defineSchema({ users: { schema: { type: "object", properties: { id: { type: "string" }, name: { type: "string" }, }, required: ["id", "name"], }, keys: [{ property: "id" }], }, });
// Start in-memory, later point this to postgresql://... or ./local.db const db = await Ominipg.connect({ url: ":memory:", schemas, });
await db.crud.users.insertOne({ id: "1", name: "Alice", });
const activeUsers = await db.crud.users.find({ name: { $in: ["Alice"] }, });
Links:
- JSR: https://jsr.io/@oxian/ominipg
- GitHub: https://github.com/AxionCompany/ominipg
• A bit about me / what I’m looking for
I’m a co-founder of a software development agency in Brazil. We’ve shipped 500+ projects (many enterprise), and a lot of our success has come from investing in developer productivity and internal tooling, including early bets on the Deno ecosystem. We recently decided to open-source some of these tools. Ominipg is the first of several, I’d love to get feedback from the JS (specially Deno) ecosystem.
In particular, I’d appreciate thoughts on: - The API design (especially the CRUD + schema approach) - The local + remote sync model - Rough edges you hit trying it in a small demo or side project