Sửa lỗi 'Error: connect ECONNREFUSED 127.0.0.1:5432' trong Node.js

beginner💚 Node.js2026-05-09| Node.js (v14+), PostgreSQL / MySQL / Redis / bất kỳ TCP server nào, Linux / macOS / Windows

Error Message

Error: connect ECONNREFUSED 127.0.0.1:5432
#nodejs#network#database

Lỗi Gặp Phải

Bạn chạy ứng dụng Node.js và nó bị crash — ngay lập tức hoặc giữa chừng một request — với thông báo kiểu như:

Error: connect ECONNREFUSED 127.0.0.1:5432
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1187:16) {
  errno: -111,
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 5432
}

Số port thay đổi tùy theo dịch vụ bạn đang kết nối: 5432 cho PostgreSQL, 3306 cho MySQL, 6379 cho Redis, 27017 cho MongoDB, hoặc port tùy chỉnh mà dịch vụ của bạn sử dụng. Nguyên nhân gốc rễ luôn giống nhau: Node.js cố mở một kết nối TCP đến địa chỉ và port đó, nhưng không có gì phản hồi.

Nguyên Nhân Gốc Rễ

  • Database hoặc dịch vụ đơn giản là không chạy.
  • Dịch vụ đang chạy nhưng trên port khác với những gì config của bạn kỳ vọng.
  • Dịch vụ được bind vào một interface khác (ví dụ: ::1 IPv6 thay vì 127.0.0.1 IPv4).
  • Firewall hoặc Docker network đang chặn kết nối.
  • Ứng dụng của bạn khởi động trước khi database hoàn tất quá trình boot (race condition trong Docker Compose).
  • Sai host/port trong connection string hoặc file .env.

Bước 1 — Kiểm Tra Dịch Vụ Có Đang Chạy Không

Cách này giải quyết được 90% trường hợp.

Linux / macOS

# Kiểm tra xem có gì đang lắng nghe trên port mục tiêu không
sudo ss -tlnp | grep 5432
# hoặc
sudo lsof -i :5432

Không có kết quả nghĩa là dịch vụ đang dừng. Hãy khởi động nó:

# PostgreSQL
sudo systemctl start postgresql

# MySQL / MariaDB
sudo systemctl start mysql

# Redis
sudo systemctl start redis

Windows

netstat -ano | findstr :5432

Không thấy gì? Mở Services (services.msc) và khởi động dịch vụ tương ứng, hoặc dùng lệnh khởi động riêng của ứng dụng đó.

Bước 2 — Xác Minh Config Kết Nối

Dịch vụ đã chạy? Bây giờ hãy chắc chắn ứng dụng của bạn đang trỏ đúng chỗ. Một file .env cũ hoặc một ký tự gõ sai cũng đủ để phá vỡ kết nối.

# Ví dụ file .env
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=myuser
DB_PASSWORD=secret
DB_NAME=mydb

Đối chiếu với những gì thực sự có trong code kết nối của bạn:

// pg (node-postgres)
const { Pool } = require('pg');
const pool = new Pool({
  host: process.env.DB_HOST,
  port: Number(process.env.DB_PORT),
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME,
});

In ra giá trị thực tế trước khi kết nối — đừng đoán mò:

console.log('Connecting to', process.env.DB_HOST, ':', process.env.DB_PORT);

Bước 3 — Kiểm Tra Bind Address (IPv4 vs IPv6)

Một số cài đặt chỉ bind vào ::1 (IPv6 loopback), trong khi ứng dụng của bạn lại kết nối tới 127.0.0.1 (IPv4). Trông chúng giống nhau, nhưng thực ra không phải — đây là hai socket hoàn toàn riêng biệt.

sudo ss -tlnp | grep 5432
# Nếu bạn thấy  *:5432  hoặc  :::5432 — nghĩa là chỉ có IPv6

Cách nhanh: chuyển host thành localhost và để Node.js tự resolve, hoặc dùng trực tiếp ::1:

DB_HOST=localhost   # Node tự resolve sang interface nào khả dụng

Hoặc, hãy bảo PostgreSQL bind cả hai interface bằng cách chỉnh postgresql.conf:

listen_addresses = 'localhost'   # lắng nghe trên cả 127.0.0.1 và ::1

Bước 4 — Race Condition Trong Docker Compose

Bạn đang chạy Node.js và database cùng nhau trong Docker Compose? Container app của bạn gần như chắc chắn khởi động trước khi DB sẵn sàng. depends_on không giúp được ở đây — nó chỉ chờ container khởi động, không phải chờ PostgreSQL bên trong hoàn tất quá trình boot.

Cách khắc phục là dùng health check kết hợp với condition: service_healthy:

services:
  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  app:
    build: .
    depends_on:
      db:
        condition: service_healthy
    environment:
      DB_HOST: db
      DB_PORT: 5432

Lưu ý: trong Docker Compose, hãy dùng tên service (db) làm host, không phải 127.0.0.1.

Bước 5 — Thêm Retry Logic Vào Ứng Dụng

Một lỗi ECONNREFUSED không nên làm sập toàn bộ tiến trình của bạn. Hãy thêm vòng lặp retry — chỉ cần khoảng 15 dòng code và sẽ giúp bạn tránh được nhiều đêm trực chiến căng thẳng:

const { Pool } = require('pg');

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

async function connectWithRetry(retries = 5, delay = 2000) {
  for (let i = 0; i  setTimeout(r, delay));
    }
  }
  throw new Error('Could not connect to database after multiple retries');
}

connectWithRetry();

Xác Minh Kết Nối

Trước khi khởi động lại toàn bộ ứng dụng, hãy xác nhận kết nối hoạt động ở cấp độ TCP:

# Kiểm tra kết nối TCP trực tiếp
nc -zv 127.0.0.1 5432
# Kết quả mong đợi: Connection to 127.0.0.1 5432 port [tcp/postgresql] succeeded!

# PostgreSQL: kiểm tra đăng nhập
psql -h 127.0.0.1 -p 5432 -U myuser -d mydb -c 'SELECT 1;'

# MySQL:
mysql -h 127.0.0.1 -P 3306 -u myuser -p mydb -e 'SELECT 1;'

# Redis:
redis-cli -h 127.0.0.1 -p 6379 ping
# Kết quả mong đợi: PONG

Tham Khảo Nhanh Theo Port

  • 5432 — PostgreSQL: sudo systemctl start postgresql
  • 3306 — MySQL/MariaDB: sudo systemctl start mysql
  • 6379 — Redis: sudo systemctl start redis
  • 27017 — MongoDB: sudo systemctl start mongod

Mẹo Hữu Ích

Đang làm việc với container hoặc cấu hình mạng tùy chỉnh? Subnet Calculator trên ToolCraft cho phép bạn kiểm tra dải CIDR và xác nhận rằng IP của container nằm trong mạng đúng. Chạy hoàn toàn trên trình duyệt — không tải lên bất cứ dữ liệu nào.

Related Error Notes