{"id":"2bb4da8665144586","repo":"drizzle-team/drizzle-orm","slug":"no-transactions-support-in-neon-http-driver","errorCode":null,"errorMessage":"No transactions support in neon-http driver","messagePattern":"No transactions support in neon-http driver","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"drizzle-orm/src/neon-http/session.ts","lineNumber":253,"sourceCode":"\n\toverride async count(sql: SQL): Promise<number>;\n\t/** @internal */\n\toverride async count(sql: SQL, token?: NeonAuthToken): Promise<number>;\n\t/** @internal */\n\toverride async count(sql: SQL, token?: NeonAuthToken): Promise<number> {\n\t\tconst res = await this.execute<{ rows: [{ count: string }] }>(sql, token);\n\n\t\treturn Number(\n\t\t\tres['rows'][0]['count'],\n\t\t);\n\t}\n\n\toverride async transaction<T>(\n\t\t_transaction: (tx: NeonTransaction<TFullSchema, TSchema>) => Promise<T>,\n\t\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\n\t\t_config: PgTransactionConfig = {},\n\t): Promise<T> {\n\t\tthrow new Error('No transactions support in neon-http driver');\n\t}\n}\n\nexport class NeonTransaction<\n\tTFullSchema extends Record<string, unknown>,\n\tTSchema extends TablesRelationalConfig,\n> extends PgTransaction<NeonHttpQueryResultHKT, TFullSchema, TSchema> {\n\tstatic override readonly [entityKind]: string = 'NeonHttpTransaction';\n\n\toverride async transaction<T>(_transaction: (tx: NeonTransaction<TFullSchema, TSchema>) => Promise<T>): Promise<T> {\n\t\tthrow new Error('No transactions support in neon-http driver');\n\t\t// const savepointName = `sp${this.nestedIndex + 1}`;\n\t\t// const tx = new NeonTransaction(this.dialect, this.session, this.schema, this.nestedIndex + 1);\n\t\t// await tx.execute(sql.raw(`savepoint ${savepointName}`));\n\t\t// try {\n\t\t// \tconst result = await transaction(tx);\n\t\t// \tawait tx.execute(sql.raw(`release savepoint ${savepointName}`));\n\t\t// \treturn result;","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-orm/src/neon-http/session.ts#L235-L271","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nimport { neon, drizzle } from 'drizzle-orm/neon-http';\nconst db = drizzle(neon(process.env.DATABASE_URL!));\nawait db.transaction(async (tx) => { /* ... */ }); // throws\n\n// after — neon-serverless WebSocket pool supports transactions\nimport { Pool } from '@neondatabase/serverless';\nimport { drizzle } from 'drizzle-orm/neon-serverless';\nconst db = drizzle(new Pool({ connectionString: process.env.DATABASE_URL! }));\nawait db.transaction(async (tx) => { /* ... */ });","handlingStrategy":"validation","validationCode":"import { NeonHttpSession } from 'drizzle-orm/neon-http';\n\nfunction supportsTransactions(db: any): boolean {\n  return !(db?.session instanceof NeonHttpSession);\n}\n\nif (!supportsTransactions(db)) {\n  throw new Error('neon-http cannot run transactions; use drizzle-orm/neon-serverless (Pool).');\n}","typeGuard":"import { NeonHttpSession } from 'drizzle-orm/neon-http';\n\nfunction isNeonHttp(db: any): boolean {\n  return db?.session instanceof NeonHttpSession;\n}","tryCatchPattern":"try {\n  await db.transaction(async (tx) => { /* ... */ });\n} catch (e) {\n  if (e instanceof Error && /No transactions support in neon-http driver/i.test(e.message)) {\n    throw new Error('Switch to drizzle-orm/neon-serverless (WebSocket Pool) for transactions.');\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["postgres","neon","neon-http","transaction","unsupported"],"analyzedSha":"b7862528fd8fc39bc2653a6c18dad7c1f4e68d10","analyzedAt":"2026-08-03T18:11:14.318Z","schemaVersion":2}