PostgreSQL dùng mô hình process-per-connection: mỗi kết nối là một process hệ điều hành riêng, không phải thread.
Chi phí đi kèm mỗi kết nối:
- Bộ nhớ riêng của backend process: work_mem cho mỗi thao tác sort/hash, temp_buffers, catalog cache, plan cache. Một kết nối idle vẫn giữ vài MB.
- Chi phí context switch của scheduler khi số process vượt xa số CPU core.
- Một số cấu trúc dùng chung (vd snapshot, lock table) phải quét theo số backend → chi phí tăng theo max_connections ngay cả khi kết nối đang idle.
Đặt max_connections = 2000 không làm server phục vụ được 2000 truy vấn song song — CPU vẫn chỉ có ngần ấy core. Kết quả thường thấy là throughput giảm vì tranh chấp và context switch, cộng nguy cơ hết RAM khi nhiều truy vấn cùng cấp phát work_mem.
Cách làm đúng: giữ max_connections ở mức vừa phải (thường vài trăm) và đặt connection pooler ở phía trước. Điểm xuất phát phổ biến cho pool size là quanh mức số core * 2 + số spindle rồi đo throughput thực tế mà điều chỉnh, thay vì tăng vô hạn.