Postgres
Use the first-party pg adapter for direct SQL-backed Paymesh persistence with transactions, raw persistence, migrations, and operational plugins.
Overview
@paymesh/postgres is the most direct first-party adapter. It uses pg underneath and implements the full Paymesh database driver contract without an ORM layer in between.
Installation
npm install @paymesh/postgres pgUsage
import { createClient } from "paymesh";
import { postgres } from "@paymesh/postgres";
import { stripe } from "@paymesh/stripe";
export const paymesh = createClient({
provider: stripe({
secret: "sk_test_123",
webhookSecret: "whsec_123",
}),
database: postgres("postgres://postgres:postgres@localhost:5432/paymesh", {
persistRaw: true,
}),
});Accepted connection inputs
The first argument accepts either:
- a connection string — the adapter creates and owns the internal
pg.Pool, closing it ondatabase.close() - an existing
pg.Poolinstance — ownership stays with your app;database.close()is a no-op
Passing a connection string
postgres("postgres://postgres:postgres@localhost:5432/paymesh")Passing an existing Pool
import { Pool } from "pg";
const pool = new Pool({
connectionString: "postgres://...",
max: 20,
});
postgres(pool)Options
The second argument accepts persistRaw plus any option that pg.Pool accepts (max, idleTimeoutMillis, connectionTimeoutMillis, ssl, etc.).
| Option | Default | Description |
|---|---|---|
persistRaw | false | Stores raw provider payloads alongside normalized records. |
max | 10 | Maximum number of clients in the pool. |
idleTimeoutMillis | 10000 | Close idle clients after this many milliseconds. |
connectionTimeoutMillis | 10000 | Timeout for acquiring a new connection. |
ssl | undefined | boolean or TLS configuration object. |
any PoolConfig key | — | Forwarded directly to the internal Pool. |
Pool-scoped options are forwarded to the internal Pool when a connection string is given, and silently ignored when an existing Pool instance is passed.
postgres("postgres://postgres:postgres@localhost:5432/paymesh", {
persistRaw: true,
max: 15,
idleTimeoutMillis: 30000,
ssl: { rejectUnauthorized: false },
})Transactions
The adapter creates a dedicated pg client for database.transaction() and wraps the callback in BEGIN, COMMIT, and ROLLBACK.
await paymesh.database?.transaction(async (tx) => {
await tx.repositories.customers.upsert(paymesh.schema, {
id: "cus_123",
provider: "stripe",
email: "team@example.com",
});
});Error behavior
Database query and transaction failures are wrapped into PaymeshError with code database_error.
That means callers can handle persistence issues through the same error type used by the rest of Paymesh.
When to choose this adapter
Use @paymesh/postgres when:
- you want the leanest stack
- your application is already comfortable with direct SQL or
pg - you want minimal abstraction between Paymesh and PostgreSQL
If your team already standardized on Drizzle or Prisma, use those adapters instead.