ECONNREFUSED 127.0.0.1:5432 in production
The errorError: connect ECONNREFUSED 127.0.0.1:5432
errno: -111,
code: 'ECONNREFUSED',
syscall: 'connect',
address: '127.0.0.1',
port: 5432
Your app is looking for Postgres on localhost, which in production means the server itself, and there is no database there. Set the real database URL in your host's production variables and redeploy.
Why it happens
127.0.0.1 (or ::1) is "this machine". Port 5432 is Postgres. Locally that is your own database. In production there is nothing listening there, so the connection is refused.
The usual reasons:
- The database URL isn't set in production. If your code passes
undefined, node-postgres falls back to its defaults, and the documented default host islocalhoston port5432. So a missing variable looks exactly like this error. - The variable is set to your local value, copied from
.env. - You run in Docker, where
localhostmeans the container itself, not the database container next to it.
Fix it by hand
- Check the variable on your host. On Vercel, open Settings, then Environment Variables, and confirm
DATABASE_URL(or whatever your code reads) exists and has Production ticked. Other hosts have the same idea under a different name. - Check the code reads it. Pass the URL explicitly so a missing value is obvious:
import pg from 'pg'; if (!process.env.DATABASE_URL) throw new Error('DATABASE_URL is not set'); const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL }); - Use a database production can reach. If the only database you have is on your laptop, create a hosted one and copy its connection string into the production variable.
- In Docker Compose, use the service name as the host. If your database service is called
db, the URL ispostgres://user:pass@db:5432/app, notlocalhost. - Redeploy. On Vercel, changed environment variables only apply to new deployments, so the running one keeps the old value until you deploy again.
- If the error changes to a timeout or
P1001, the address is now right but the database is refusing your host. See the P1001 fix.
Stop it happening again
- Fail fast at startup when a required variable is missing, so the error names the variable instead of a port.
- Never hardcode
localhostas a fallback for a database URL in code that ships. - Keep a committed
.env.examplelisting every variable production needs, and check it against your host before each deploy.
Broke After Deploy $9
Broke After Deploy flags database addresses that point at your own computer, env variables your code uses that production may not have, and config that only exists in a gitignored .env. Give it your host's variable names and missing ones become definite findings.
- Checks your project for 37 known causes of "works locally, breaks in production" and runs your production build.
- Paste the error and it finds the cause in your code, then lists what will break next.
- Verdict first. Every finding shows the file and line, what it breaks, and the fix as a diff that is applied only with your OK.
Broke After Deploy: how it works, with examples · Install guide
Works with Claude Code, Claude.ai, Cursor, Codex and other agents that read SKILL.md files. No installs, no accounts, works offline. No-questions refund.