“Giới hạn concurrency 10” và “giới hạn 100 request/giây” nghe cùng họ — đơn vị khác nhau, chữa bệnh khác nhau.
Pool / semaphore — tối đa K đang chạy (in-flight inventory)
Rate limit — tối đa N lần bắt đầu / đơn vị thời gian
(token bucket, leaky bucket, fixed window…)
Demo trực quan: pool vs rate — in-flight và starts/s.
Pool — trần inventory
- Bảo vệ RAM, DB connections, worker slots — in-flight inventory.
- Job chậm 60s, pool 10 → throughput ~10/phút dù “muốn” nhanh hơn.
- Batch vs pool — cách implement K.
Rate limit — trần tốc độ vào
- API quota, fair share multi-tenant, chống burst short.
- Job siêu nhanh: chỉ pool 10 có thể >1000 start/s — rate chặn burst.
- Job siêu chậm: rate 100/s + pool 10 → hàng đợi start, không 100 parallel.
Chỉ một cái — thiếu gì
Chỉ pool, không rate
→ start có thể cực nhanh khi job ngắn; downstream QPS nổ
→ hoặc chấp nhận nếu downstream chỉ care concurrent
Chỉ rate, không pool
→ 100 start/s × job 30s = 3000 in-flight tiềm năng → OOM
→ unbounded inventory dưới vỏ “đã rate limit”
Thường cần cả hai
rate: max 50 starts/s (bảo vệ QPS dependency)
pool: max 20 in-flight (bảo vệ memory + connection)
queue: bound (backpressure khi cả hai no)
Đầy pool / đầy queue: backpressure hoặc load shedding.
Một câu để nhớ
Pool = bao nhiêu đang ôm; rate = bao nhanh được bốc thêm.
Hai số, hai bệnh — đừng chỉ chỉnh một nút.