Demo, all content is generated
Question

Drizzle on Supabase: 'prepared statement "xyz" does not exist' only in production

Solved · 314 views · asked by tuan_ng · edited

Next.js app on Vercel, Drizzle ORM with postgres-js, Supabase database. Locally everything is fine. In production maybe one in ten requests fails with:

PostgresError: prepared statement "8f3a1c2e" does not exist

or sometimes prepared statement ... already exists. Retrying the same request usually works. My DATABASE_URL is the one from the Connect dialog with port 6543.

What I’ve tried

Claude Code suggested wrapping every query in a retry. That works but feels like a bandaid. Restarted the Supabase project, no change.

Comment

3 answers

Marked as helpful by the asker
jb_supa · edited

Port 6543 is the transaction pooler. In transaction mode each query can land on a different backend connection, so a prepared statement created on one connection isn't there on the next. postgres-js prepares statements by default.

const client = postgres(process.env.DATABASE_URL!, { prepare: false })
export const db = drizzle({ client })

Locally it works because you're probably hitting the local database directly, no pooler in between. Remove the retry wrapper after this, it hides real errors.

Comment
That was it, zero errors since. Removing the retry now. tuan_ng · edited
ximena_c · edited

If you also run drizzle-kit migrations, point those at the session pooler (port 5432) or the direct connection, not 6543. Migrations like having one connection for the whole run.

Comment
good to know, my drizzle.config uses the same URL. changing it tuan_ng · edited
nadia_r · edited

If you switch to node-postgres (pg) instead: it only prepares statements when you give a query a name, so it works with the transaction pooler out of the box. But prepare: false is the smaller change.

Comment