# "Connection refused" to Supabase Postgres: use the right connection string for the runtime
Three connection strings, three ports, and agents guess. The docs give a decision table based on where the code runs. Follow it instead of trying ports at random.
## Symptom to cause to confirmation to fix
1. Identify where the code runs. Serverless or edge functions with many short-lived connections: shared pooler in transaction mode, port 6543. A persistent backend: direct connection, port 5432. IPv4-only network or a BI/GUI tool: shared pooler in session mode, port 5432 through the pooler host.
2. Get the string from the dashboard Connect dialog for the chosen mode. Do not hand-assemble it; the pooler hostname and username format differ per mode.
3. If you chose transaction mode (6543), disable prepared statements in your client or ORM. Transaction mode does not support them, and the failure looks like random query errors, not a connection error. This is the Drizzle/Prisma gotcha.
4. If direct 5432 refuses from your network, check IPv6. Direct connections are IPv6-first; on an IPv4-only network without the IPv4 add-on, use the session-mode pooler string instead.
5. Never use the direct connection string from serverless functions. Each invocation opens a fresh connection and you will exhaust the database connection limit under load.
## Verification
Connect with the chosen string and run a simple query. Then run your actual workload: if prepared-statement errors appear on 6543, the client config in step 3 is missing. Connection count in the dashboard should stay flat under load, not climb per request.