drizzle-team/drizzle-orm · error · Error
Transactions are not supported by the Postgres Proxy driver
Error message
Transactions are not supported by the Postgres Proxy driver
What it means
This error is thrown by PgRemoteSession.transaction() because the Postgres Proxy driver (drizzle-orm/pg-proxy) executes queries over a stateless remote callback (HTTP/RPC) and cannot open a real PostgreSQL transaction. Transactions require a persistent connection, BEGIN/COMMIT, and a session that the proxy protocol does not expose. The driver overrides transaction() to fail fast rather than silently no-op.
Source
Thrown at drizzle-orm/src/pg-proxy/session.ts:74
this.client,
query.sql,
query.params,
query.typings,
this.logger,
this.cache,
queryMetadata,
cacheConfig,
fields,
isResponseInArrayMode,
customResultMapper,
);
}
override async transaction<T>(
_transaction: (tx: PgProxyTransaction<TFullSchema, TSchema>) => Promise<T>,
_config?: PgTransactionConfig,
): Promise<T> {
throw new Error('Transactions are not supported by the Postgres Proxy driver');
}
}
export class PgProxyTransaction<
TFullSchema extends Record<string, unknown>,
TSchema extends TablesRelationalConfig,
> extends PgTransaction<PgRemoteQueryResultHKT, TFullSchema, TSchema> {
static override readonly [entityKind]: string = 'PgProxyTransaction';
override async transaction<T>(
_transaction: (tx: PgProxyTransaction<TFullSchema, TSchema>) => Promise<T>,
): Promise<T> {
throw new Error('Transactions are not supported by the Postgres Proxy driver');
}
}
export class PreparedQuery<T extends PreparedQueryConfig> extends PreparedQueryBase<T> {
static override readonly [entityKind]: string = 'PgProxyPreparedQuery';View on GitHub (pinned to b7862528fd)
Solutions
- Switch to a driver that supports transactions: drizzle-orm/node-postgres, drizzle-orm/postgres-js, drizzle-orm/vercel-postgres (which supports transactions via pool), or neon-serverless with a WebSocket/HTTP transactional API.
- If you must stay on pg-proxy, restructure logic to avoid transactions: run statements sequentially and implement application-level idempotency/compensating logic instead of BEGIN/COMMIT.
- If using Supabase edge, check drizzle-orm/neon-http vs neon-serverless; neon-serverless over WebSocket supports transactions while neon-http (proxy-like) does not.
Example fix
// before (pg-proxy, throws)
import { drizzle } from 'drizzle-orm/pg-proxy';
const db = drizzle(remoteCallback);
await db.transaction(async (tx) => {
await tx.insert(users).values({...});
});
// after (postgres-js, transactions supported)
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
const db = drizzle(postgres(process.env.DATABASE_URL!));
await db.transaction(async (tx) => {
await tx.insert(users).values({...});
}); Defensive patterns
Strategy: validation
Validate before calling
// Before using transactions, detect the proxy driver and branch.
import { is } from 'drizzle-orm/entity';
import { PgRemoteSession } from 'drizzle-orm/pg-proxy/session';
function supportsTransactions(db: any): boolean {
// The pg-proxy session's transaction is the throwing override;
// treat PgRemoteSession as unsupported.
return !is(db.$client, PgRemoteSession) && !is(db.session, PgRemoteSession);
}
if (supportsTransactions(db)) {
await db.transaction(async (tx) => { /* ... */ });
} else {
await runSequentiallyWithoutTransaction();
} Type guard
import { entityKind } from 'drizzle-orm/entity';
function isPgProxyDb(db: any): boolean {
const session = db?.session;
return session?.[entityKind] === 'PgRemoteSession';
} Try / catch
try {
await db.transaction(async (tx) => { /* ... */ });
} catch (e) {
if (e instanceof Error && /Transactions are not supported by the Postgres Proxy driver/.test(e.message)) {
// fall back to sequential non-transactional writes with compensation
} else throw e;
} Prevention
- Decide your driver based on whether you need transactions before wiring Drizzle into the app.
- Encapsulate db.transaction calls behind a repository interface so the driver can be swapped without touching call sites.
- In serverless/edge deployments, prefer drivers documented to support transactions (neon-serverless over WS, vercel-postgres pool).
When it happens
Trigger: Calling db.transaction(async (tx) => {...}) on a database instance built with drizzle()'s pg-proxy driver (RemoteCallback). This includes any relational query builder that internally needs a transaction, or direct use of db.transaction() in application code after initializing via drizzle(remoteCallback).
Common situations: Developers migrating from node-postgres or pg-driver code that used transactions, then deploying to an edge/serverless platform with the pg-proxy driver. Copying example transaction code from docs that assumes a socket driver. Using the Supabase/Neon HTTP RPC edge driver and attempting transactions.
Related errors
- Warning: You need to pass an instance of Client: import { C
- Transaction not supported
- No transactions support in neon-http driver
- crudPolicy requires a read policy
- crudPolicy requires a modify policy
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/49bb29099f68048d.json.
Report an issue: GitHub.