drizzle-team/drizzle-orm · error · Error
No transactions support in neon-http driver
Error message
No transactions support in neon-http driver
What it means
An Error 'No transactions support in neon-http driver' thrown by NeonHttpSession.transaction() (drizzle-orm/src/neon-http/session.ts:253). The neon-http driver issues each query as an independent HTTPS fetch to Neon; there is no persistent connection over which to hold a transaction open, so db.transaction() is intentionally unimplemented and throws synchronously.
Source
Thrown at drizzle-orm/src/neon-http/session.ts:253
override async count(sql: SQL): Promise<number>;
/** @internal */
override async count(sql: SQL, token?: NeonAuthToken): Promise<number>;
/** @internal */
override async count(sql: SQL, token?: NeonAuthToken): Promise<number> {
const res = await this.execute<{ rows: [{ count: string }] }>(sql, token);
return Number(
res['rows'][0]['count'],
);
}
override async transaction<T>(
_transaction: (tx: NeonTransaction<TFullSchema, TSchema>) => Promise<T>,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_config: PgTransactionConfig = {},
): Promise<T> {
throw new Error('No transactions support in neon-http driver');
}
}
export class NeonTransaction<
TFullSchema extends Record<string, unknown>,
TSchema extends TablesRelationalConfig,
> extends PgTransaction<NeonHttpQueryResultHKT, TFullSchema, TSchema> {
static override readonly [entityKind]: string = 'NeonHttpTransaction';
override async transaction<T>(_transaction: (tx: NeonTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T> {
throw new Error('No transactions support in neon-http driver');
// const savepointName = `sp${this.nestedIndex + 1}`;
// const tx = new NeonTransaction(this.dialect, this.session, this.schema, this.nestedIndex + 1);
// await tx.execute(sql.raw(`savepoint ${savepointName}`));
// try {
// const result = await transaction(tx);
// await tx.execute(sql.raw(`release savepoint ${savepointName}`));
// return result;View on GitHub (pinned to b7862528fd)
Solutions
- Switch to drizzle-orm/neon-serverless with a WebSocket Pool (@neondatabase/serverless Pool) which supports transactions.
- Or use drizzle-orm/node-postgres against Neon for serverful apps.
- If staying on neon-http, restructure to single statements or use Neon's HTTP transaction endpoint if available.
Example fix
// before
import { neon, drizzle } from 'drizzle-orm/neon-http';
const db = drizzle(neon(process.env.DATABASE_URL!));
await db.transaction(async (tx) => { /* ... */ }); // throws
// after — neon-serverless WebSocket pool supports transactions
import { Pool } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-serverless';
const db = drizzle(new Pool({ connectionString: process.env.DATABASE_URL! }));
await db.transaction(async (tx) => { /* ... */ }); Defensive patterns
Strategy: validation
Validate before calling
import { NeonHttpSession } from 'drizzle-orm/neon-http';
function supportsTransactions(db: any): boolean {
return !(db?.session instanceof NeonHttpSession);
}
if (!supportsTransactions(db)) {
throw new Error('neon-http cannot run transactions; use drizzle-orm/neon-serverless (Pool).');
} Type guard
import { NeonHttpSession } from 'drizzle-orm/neon-http';
function isNeonHttp(db: any): boolean {
return db?.session instanceof NeonHttpSession;
} Try / catch
try {
await db.transaction(async (tx) => { /* ... */ });
} catch (e) {
if (e instanceof Error && /No transactions support in neon-http driver/i.test(e.message)) {
throw new Error('Switch to drizzle-orm/neon-serverless (WebSocket Pool) for transactions.');
}
throw e;
} Prevention
- Before choosing neon-http, audit for db.transaction() usage; if present, use neon-serverless.
- Keep transactional logic behind a DAO that can swap drivers.
- Document that neon-http is transaction-free for edge cold-starts.
When it happens
Trigger: Constructing the DB with drizzle-orm/neon-http's drizzle(neon(process.env.DATABASE_URL)) and calling db.transaction(async tx => { ... }). The override throws immediately regardless of config.
Common situations: Using neon-http for cheapest cold-start in serverless/edge, then reaching for db.transaction() in business logic. Developers expect transaction support because Neon is a real Postgres, but the HTTP transport cannot keep a tx alive between round trips.
Related errors
- Transactions are not supported by the MySql Proxy driver
- crudPolicy requires a read policy
- crudPolicy requires a modify policy
- Transactions are not supported by the SingleStore Proxy driv
- Rollback
AI-assisted analysis of drizzle-team/drizzle-orm@b7862528fd (2026-08-03).
Data as JSON: /data/errors/2bb4da8665144586.json.
Report an issue: GitHub.