Node chỉ chạy JavaScript trên một thread, nhưng libuv giữ một thread pool để làm những việc hệ điều hành không cung cấp API bất đồng bộ tốt. Mặc định pool có 4 thread, chỉnh qua biến môi trường UV_THREADPOOL_SIZE (tối đa 1024, phải đặt trước khi thread pool được dùng lần đầu).
Dùng thread pool:
- fs.* (mọi thao tác file, trừ FSWatcher)
- dns.lookup() (vì nó gọi getaddrinfo của hệ thống)
- Một số hàm crypto: pbkdf2, scrypt, randomBytes, randomFill
- zlib (nén/giải nén)
Không dùng thread pool — chạy trên epoll/kqueue của kernel, gần như không giới hạn số kết nối song song:
- TCP/HTTP socket (net, http, https)
- dns.resolve*() (tự query DNS qua socket)
Triệu chứng hay gặp khi phỏng vấn hỏi: API hash mật khẩu bằng pbkdf2/bcrypt, đo thấy 4 request đầu nhanh, request thứ 5 phải xếp hàng đợi — vì pool chỉ có 4 thread. Tăng UV_THREADPOOL_SIZE lên xấp xỉ số core giúp phần nào, nhưng tăng vô tội vạ chỉ đổi chỗ nghẽn sang tranh chấp CPU. Với việc CPU nặng và kéo dài, giải pháp đúng là worker pool riêng hoặc đẩy sang job queue.