Thứ Tư, 2 tháng 9, 2026

API Rate Limiting là gì? (Vì sao Server không cho bạn gọi API 10.000 lần trong 1 phút?)

Đã bao giờ bạn "hiên ngang" bước vào một quán phở và "hùng dũng" gọi: cho 100 tô phở tái. 100 tô phở tái gân, 100 tô phở tái nạm gàu, 100 tô phở đặc biệt, 100 tô phở tái không hành, 100 tô phở tái nạm không hành.....Phù.....viết không thôi đã đủ mệt rồi!

Ở bài trước.

Chúng ta vừa học:

Authorization.

Server không chỉ hỏi:

"Anh là ai?"

mà còn hỏi:

"Anh được phép làm gì?"

😎

Nhưng giả sử bạn đã:

  • đăng nhập đúng,
  • có Token hợp lệ,
  • có quyền truy cập API,
  • không làm gì sai...

thì bạn có thể gọi API:

10 lần?
100 lần?
1.000 lần?
10.000 lần?

trong một phút không?

🤔

Server:

"Không nhé."

🤣

Và đó chính là lúc:

API Rate Limiting xuất hiện.


API Rate Limiting là gì?

API Rate Limiting là cơ chế giới hạn số lượng request mà một user, IP, API Key hoặc client được phép gửi đến API trong một khoảng thời gian nhất định.

Ví dụ:

100 requests / phút

có nghĩa là client chỉ được phép gửi tối đa 100 request trong một phút theo chính sách của API.

Nếu vượt quá giới hạn:

429 Too Many Requests

có thể được trả về.

Rate Limiting giúp:

  • bảo vệ Server,
  • giảm tải Database,
  • chống lạm dụng API,
  • hạn chế request tự động quá mức,
  • tăng tính ổn định của hệ thống.



Ví dụ đời thường nhất 🚦

Hãy tưởng tượng một nhà hàng.

🍜

Nhà hàng có:

100 chỗ ngồi

Một người bước vào.

Ăn xong.

Đi ra.

OK.

Nhưng nếu một người chạy vào:

1
2
3
4
5
...
1000 lần

trong vài phút.

Nhân viên:

"Anh vào đây ăn hay tập thể dục vậy?" 😭

🤣

Nhà hàng phải đặt quy định:

"Mỗi người chỉ được gọi tối đa 5 món trong một lần."

Đó chính là tư duy của Rate Limiting.

API cũng vậy.

Server nói:

"Anh có quyền gọi API."

Nhưng:

"Không có nghĩa là anh muốn gọi bao nhiêu lần cũng được."


"Chua thêm" 😆

Rate Limiting giống như:

đèn giao thông.

Bạn được phép đi.

🚗

Nhưng không có nghĩa:

"Được phép đi"

=>

"Muốn chạy 300 km/h lúc nào cũng được."

🤣

API cũng vậy:

Authentication
→ Anh là ai?

Authorization
→ Anh được phép làm gì?

Rate Limiting
→ Anh được phép làm việc đó bao nhiêu lần trong khoảng thời gian này?

Ba câu hỏi.

Ba vấn đề khác nhau.


Tại sao API cần Rate Limiting?

Có rất nhiều lý do.

1. Bảo vệ Server 🛡️

Giả sử API:

GET /api/products

bình thường mỗi user gọi:

10 requests/phút

Nhưng một chương trình nào đó gọi:

100.000 requests/phút

Server sẽ phải xử lý một lượng request khổng lồ.

Nếu có nhiều client cùng làm vậy:

😵

Server có thể quá tải.


2. Bảo vệ Database 🗄️

Đây mới là phần rất đáng quan tâm với PHP/MySQL newbie.

API:

GET /api/products

có thể thực hiện:

SELECT ...
FROM products
...

Mỗi request:

API
 ↓
PHP
 ↓
MySQL

Một request không đáng sợ.

Nhưng:

10.000 requests

thì Database có thể phải xử lý:

10.000 queries

hoặc nhiều hơn nếu mỗi request thực hiện nhiều query.

Database:

"Tôi chỉ là Database thôi mà..." 😭

🤣


3. Ngăn Abuse

Không phải mọi request đều là request của người dùng bình thường.

Có thể là:

  • Bot
  • Script tự động
  • Crawler
  • Tool thử API
  • Client bị lỗi
  • Một chương trình gọi API quá nhanh

Rate Limiting giúp hạn chế những trường hợp này.


4. Hạn chế Brute Force 🔐

Đây là một ứng dụng rất quan trọng.

Giả sử API login:

POST /api/login

Nếu Server cho phép thử:

1.000.000 lần/phút

😱

Một kẻ tấn công có thể thử rất nhiều mật khẩu.

Nếu có Rate Limiting:

5 login attempts / phút

thì tốc độ thử bị giảm đáng kể.

Rate Limiting không phải toàn bộ giải pháp bảo mật cho login, nhưng là một lớp phòng vệ rất hữu ích.


5. Bảo vệ API khỏi Client bị lỗi 🤦

Không phải lúc nào request quá nhiều cũng do hacker.

Đôi khi chính lập trình viên gây ra.

Ví dụ Frontend có bug:

setInterval(() => {
    fetch('/api/products');
}, 10);

😱

Cứ mỗi:

10 milliseconds

lại gọi API.

Server:

GET
GET
GET
GET
GET
GET
...

Frontend:

"Em chỉ muốn cập nhật dữ liệu thôi mà."

Server:

"Em đang DDOS anh đấy!" 😭

🤣

Rate Limiting có thể trở thành "phanh khẩn cấp".


Rate Limit hoạt động thế nào?

Ví dụ Server đặt:

100 requests / minute

Client gửi:

Request 1
Request 2
Request 3
...
Request 100

→ OK.

Request thứ:

101

Server:

429 Too Many Requests

🚦

Thông điệp rất rõ:

"Chậm lại anh ơi."


HTTP 429 là gì?

Đây là HTTP Status Code rất đáng nhớ.

429 Too Many Requests

Nghĩa đơn giản:

Bạn đã gửi quá nhiều request trong khoảng thời gian được cho phép.

Ví dụ:

GET /api/products

Response:

HTTP/1.1 429 Too Many Requests

Client nên hiểu:

"Server đang bảo mình giảm tốc độ."

Không phải:

"API chết rồi."

😄


429 khác 401 và 403 thế nào?

Chúng ta đã gặp hai anh:

401
403

Bây giờ có thêm:

429
StatusÝ nghĩa đơn giản
401Chưa xác thực hợp lệ
403Đã xác thực nhưng không có quyền
429Gửi quá nhiều request

Ví dụ:

Không có Token
→ 401
Có Token nhưng không có quyền
→ 403
Có Token + có quyền nhưng gọi quá nhanh
→ 429

😎


Rate Limiting không có nghĩa là "cấm"

Đây là một hiểu lầm khá phổ biến.

Nếu API quy định:

100 requests / phút

thì không có nghĩa:

"User chỉ được gọi API 100 lần rồi bị khóa vĩnh viễn."

Không.

Thông thường đó là:

Giới hạn trong một khoảng thời gian.

Ví dụ:

14:00:00 → 100 requests
14:01:00 → quota được tính lại

Cách tính chính xác phụ thuộc vào cơ chế Rate Limiting mà hệ thống sử dụng.


Có những kiểu Rate Limiting nào?

Có nhiều thuật toán.

Nghe tên có vẻ hơi "Backend":

  • Fixed Window
  • Sliding Window
  • Token Bucket
  • Leaky Bucket

😅

Nhưng đừng hoảng.

Ý tưởng chung vẫn là:

Đếm hoặc kiểm soát tốc độ request trong một khoảng thời gian.


Fixed Window

Ví dụ:

100 requests / phút

Server chia thời gian thành từng cửa sổ:

14:00 → 14:01
14:01 → 14:02
14:02 → 14:03

Trong mỗi cửa sổ:

Tối đa 100 requests

Dễ hiểu.

Dễ triển khai.

Nhưng có một vấn đề ở ranh giới giữa hai cửa sổ.

Ví dụ:

14:00:59
→ 100 requests

14:01:00
→ thêm 100 requests

😵

Trong khoảng thời gian rất ngắn có thể xuất hiện lượng request lớn.

Đây là lý do các hệ thống thực tế có thể dùng những cách tinh vi hơn.


Sliding Window

Thay vì nhìn cứng theo:

14:00 → 14:01

hệ thống nhìn một khoảng thời gian "trượt" theo thời điểm hiện tại.

Ví dụ:

"Trong 60 giây gần nhất, anh đã gọi bao nhiêu request?"

Cách này giúp kiểm soát mượt hơn trong một số trường hợp.


Token Bucket 🪣

Tên nghe vui đúng không?

Bucket = cái xô.

Hãy tưởng tượng Server có một cái xô chứa:

100 token

Mỗi request lấy:

1 token

Hết token:

"Hết vé."

🤣

Sau đó token được nạp lại theo tốc độ nhất định.

Ví dụ:

Bucket capacity = 100
Refill = 10 token/giây

Client có thể gửi request trong giới hạn số token có sẵn.

Đây là một cách rất phổ biến để mô hình hóa giới hạn tốc độ.


Leaky Bucket 💧

Hãy tưởng tượng một cái xô có lỗ nhỏ.

Request đổ vào.

Nhưng dữ liệu chỉ được xử lý ra với tốc độ nhất định.

Nếu request đến quá nhanh:

Request
Request
Request
Request
Request
...

xô có thể đầy.

→ Request mới có thể bị từ chối.

😄

Đây là cách hình dung đơn giản về Leaky Bucket.


Rate Limit dựa trên cái gì?

Đây là câu hỏi rất hay.

Server có thể giới hạn theo:

IP

Ví dụ:

100 requests / minute / IP

Một IP gửi quá nhiều request:

→ 429.


User

Ví dụ:

1000 requests / hour / user

User đăng nhập nào có quota riêng.


API Key

Ví dụ:

API Key A → 10.000 requests/day
API Key B → 100.000 requests/day

Phù hợp với các API dành cho developer hoặc ứng dụng bên ngoài.


Endpoint

Có thể mỗi API có giới hạn khác nhau.

Ví dụ:

GET /api/products
→ 1000/minute

nhưng:

POST /api/login
→ 5/minute

Rất hợp lý.

Vì Login thường cần bảo vệ chặt hơn.


Không phải API nào cũng có cùng Rate Limit

Ví dụ:

GET /api/products

rất nhẹ.

Bạn có thể cho:

1000 requests/minute

Nhưng:

POST /api/generate-report

có thể rất nặng.

Mỗi request mất:

5 giây CPU

hoặc truy vấn rất nhiều dữ liệu.

Không thể cho cùng một Rate Limit.

Có thể chỉ cho:

10 requests/minute

Đây là lý do Rate Limiting nên dựa trên đặc điểm của endpoint.


Rate Limit có thể khác nhau theo User

Ví dụ một API SaaS:

Free
→ 100 requests/hour

Pro
→ 10.000 requests/hour

Enterprise
→ 1.000.000 requests/hour

😎

Không phải vì Server "thiên vị".

Mà vì:

  • Gói dịch vụ khác nhau.
  • Tài nguyên sử dụng khác nhau.
  • Business model khác nhau.

API nên thông báo Rate Limit cho Client

Một API tốt không nên chỉ nói:

429

rồi bỏ mặc Client.

API có thể cung cấp thông tin như:

Limit
Remaining
Reset

Ví dụ:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 20

Ý nghĩa:

Limit = 100
Remaining = 20

Client biết:

"Tôi còn 20 request."

Một số API còn cung cấp thời điểm hoặc số giây cần chờ trước khi thử lại, chẳng hạn qua:

Retry-After

Retry-After là gì?

Giả sử API trả:

429 Too Many Requests
Retry-After: 30

Có thể hiểu:

"Đợi khoảng 30 giây rồi thử lại."

😄

Client nên tôn trọng thông tin này thay vì:

429
↓
thử lại ngay
↓
429
↓
thử lại ngay
↓
429
↓
...

🤣

Làm vậy chỉ khiến tình hình tệ hơn.


Đây là lúc Exponential Backoff xuất hiện 📈

Một cách phổ biến để Client retry là:

1 giây
2 giây
4 giây
8 giây
16 giây
...

Thay vì:

retry
retry
retry
retry
retry

liên tục.

Đây gọi là:

Exponential Backoff.

Ý tưởng:

Càng bị từ chối nhiều, càng chờ lâu trước khi thử lại.

Rất hữu ích khi hệ thống đang quá tải hoặc có giới hạn request.


"Chua thêm" lần 3 🤣

Hãy tưởng tượng bạn gọi điện cho một nhà hàng:

"Alo?"

Nhà hàng:

"Đang bận."

Bạn:

"Alo?"

"Đang bận."

"Alo?"

"Đang bận."

Bạn:

"Alo?"

"ĐANG BẬN!!!" 😭

🤣

Cách thông minh hơn:

"OK. Tôi đợi 30 giây rồi gọi lại."

Đó chính là tư duy của:

Retry + Backoff.


Rate Limiting và Pagination có liên quan không?

Có.

Hai kỹ thuật này giải quyết hai vấn đề khác nhau.

Pagination

Giới hạn:

Bao nhiêu dữ liệu trong một response?

Rate Limiting

Giới hạn:

Bao nhiêu request trong một khoảng thời gian?

Ví dụ:

Pagination:
20 products / request

và:

Rate Limit:
100 requests / minute

Bạn có thể có cả hai.


Ví dụ API hoàn chỉnh

Frontend muốn lấy danh sách sản phẩm.

Request:

GET /api/products?page=1&limit=20
Authorization: Bearer TOKEN

Server kiểm tra:

Bước 1

Token hợp lệ?

→ Authentication.

Bước 2

User có quyền xem products?

→ Authorization.

Bước 3

User có vượt Rate Limit?

→ Rate Limiting.

Bước 4

Pagination hợp lệ?

page=1, limit=20.

Bước 5

Query Database.

Bước 6

Trả JSON.

🎉

Ta có:

Request
   ↓
Authentication
   ↓
Authorization
   ↓
Rate Limiting
   ↓
Pagination
   ↓
Database
   ↓
JSON
   ↓
Frontend

Đây chính là một Backend flow rất thực tế.


Rate Limiting đặt ở đâu?

Không nhất thiết chỉ ở PHP.

Có thể triển khai ở nhiều tầng:

Client
 ↓
CDN / Reverse Proxy
 ↓
Web Server
 ↓
Application
 ↓
Database

Ví dụ:

  • Cloudflare
  • Nginx
  • API Gateway
  • Application Framework
  • Redis
  • Database-backed counter

Mỗi tầng có thể đóng một vai trò khác nhau.

Với người mới làm PHP:

Đừng cố xây hệ thống Rate Limiting khổng lồ ngay từ đầu.

Hiểu nguyên lý trước.

Sau đó mới học cách triển khai.


Rate Limiting trong PHP

Một cách đơn giản về mặt tư duy:

if ($request_count > $limit) {
    http_response_code(429);
    exit;
}

Nhưng...

😅

Đây chỉ là minh họa ý tưởng.

Trong hệ thống thật, bạn cần:

  • xác định client,
  • lưu số request,
  • xác định time window,
  • xử lý đồng thời,
  • reset counter,
  • tránh race condition,
  • chọn storage phù hợp.

Nếu traffic lớn.

Không nên chỉ dựa vào một biến PHP:

$count++;

rồi hy vọng mọi thứ ổn.

🤣

PHP request kết thúc thì biến đó cũng biến mất.

Bạn cần một nơi lưu trạng thái phù hợp.


Redis thường xuất hiện ở đây

Trong các hệ thống lớn, bạn có thể gặp:

Redis

để lưu counter/rate-limit state.

Ví dụ tư duy:

User 25
   ↓
Redis
   ↓
requests = 87
   ↓
limit = 100

Request tiếp theo:

88

→ OK.

...

Request:

101

→ 429.

Redis phù hợp với các bài toán cần thao tác counter nhanh, nhưng cách triển khai cụ thể phụ thuộc kiến trúc hệ thống.


Laravel có Rate Limiting không?

Có.

Laravel cung cấp cơ chế hỗ trợ Rate Limiting và Throttling để giới hạn request.

Ví dụ bạn sẽ gặp những khái niệm như:

RateLimiter
throttle middleware

Tư duy vẫn giống nhau:

Request
 ↓
Throttle
 ↓
Còn quota?
 ↓
YES → tiếp tục
NO  → 429

Đây là một trong những lý do Framework giúp developer không phải tự xây mọi thứ từ số 0.


Một lỗi newbie rất dễ mắc 🤦

Bạn test API bằng Postman.

Bấm:

Send

Send

Send

Send

Send

...

Rồi đột nhiên:

429 Too Many Requests

Bạn:

"API hỏng rồi!" 😱

Không.

API đang làm đúng nhiệm vụ.

🤣

Hãy kiểm tra:

  • Rate Limit bao nhiêu?
  • Window bao lâu?
  • Retry-After không?
  • User/IP nào đang bị giới hạn?
  • Có request tự động nào đang chạy không?

Một lỗi còn buồn cười hơn 🤣

Frontend có bug.

Code:

fetch('/api/products');

nằm trong một đoạn code được chạy lại mỗi lần component render.

Component render:

1
2
3
4
5
...

API:

GET
GET
GET
GET
GET
...

Sau một lúc:

429

Developer:

"Sao API hôm nay khó ở vậy?"

🤣

Thực ra API đang nói:

"Anh tự sửa Frontend đi."

Đây là lý do khi gặp 429:

đừng vội tăng Rate Limit.

Hãy tìm nguyên nhân request quá nhiều trước.


Rate Limiting có thay thế Security không?

Không.

Rate Limiting chỉ là một lớp bảo vệ.

Nó không thay thế:

  • Authentication
  • Authorization
  • Input Validation
  • Prepared Statements
  • HTTPS
  • Access Control
  • Logging
  • Monitoring

Một hệ thống an toàn thường có nhiều lớp.

Có thể hình dung:

Authentication
      ↓
Authorization
      ↓
Validation
      ↓
Rate Limiting
      ↓
Database Security
      ↓
Logging / Monitoring

Không có "một chiếc khóa thần kỳ" bảo vệ toàn bộ API.


Rate Limiting có thể gây khó chịu không? 😅

Có.

Nếu đặt quá thấp:

10 requests / minute

trong khi Frontend thực sự cần:

30 requests / minute

thì user bình thường cũng bị:

429

😵

Ngược lại.

Nếu đặt quá cao:

1.000.000 requests / minute

thì Rate Limiting gần như vô nghĩa.

Vì vậy phải cân bằng:

Đủ chặt để bảo vệ hệ thống, đủ rộng để user bình thường không bị vướng.


Rate Limit nên thiết kế thế nào?

Không có một con số thần kỳ.

Hãy xem:

1. Endpoint làm gì?

Đọc dữ liệu đơn giản?

Hay xử lý nặng?

2. User bình thường gọi bao nhiêu?

Đừng đoán.

Hãy quan sát.

3. Database chịu được bao nhiêu?

4. Có Cache không?

5. Có nhiều loại User không?

6. Có API public không?

Public API thường cần kiểm soát rất kỹ.


Debug 429 kiểu dev thật 🔍

Khi gặp:

429 Too Many Requests

đừng ngay lập tức:

"Tăng limit lên!" 😭

Hãy làm từng bước.

1. Kiểm tra Network

Mở:

DevTools → Network

Xem API bị gọi bao nhiêu lần.


2. Kiểm tra Request

Ví dụ:

GET /api/products

Có bị gọi lặp lại không?


3. Kiểm tra Response Headers

Tìm:

RateLimit
X-RateLimit
Retry-After

nếu API cung cấp.


4. Kiểm tra khoảng thời gian

Ví dụ:

100 requests / minute

Bạn có thực sự gửi hơn 100 request không?


5. Kiểm tra Frontend

Có:

loop
timer
retry
polling
component re-render

gây request lặp không?


6. Kiểm tra Backend

Có endpoint nào vô tình gọi chính nó hoặc gọi API khác liên tục không?


Một bài học rất quan trọng

Khi API trả:

429

đừng chỉ nghĩ:

"Server giới hạn tôi."

Hãy nghĩ:

"Tại sao tôi đang gửi nhiều request đến mức Server phải giới hạn tôi?"

Đây là tư duy Debug.

Không chỉ chữa triệu chứng.

Mà tìm nguyên nhân.

😎


Checklist chuẩn không cần chỉnh 🚦

  • Rate Limiting = giới hạn số request trong một khoảng thời gian.

  • 429 Too Many Requests = gửi quá nhiều request.

  • Authentication không thay thế Rate Limiting.

  • Authorization không thay thế Rate Limiting.

  • Pagination giới hạn dữ liệu mỗi response.

  • Rate Limiting giới hạn tốc độ request.

  • Có thể giới hạn theo IP, User, API Key hoặc Endpoint.

  • Login thường cần Rate Limiting chặt hơn các API đọc dữ liệu.

  • Có thể dùng Retry-After để báo Client thời gian chờ.

  • Client nên sử dụng Backoff khi retry.

  • Không nên retry 429 liên tục.

  • Frontend bug cũng có thể tạo ra hàng nghìn request.

  • Đừng vội tăng Rate Limit khi gặp 429.

  • Kiểm tra DevTools → Network khi debug.

  • Với hệ thống lớn, Rate Limiting có thể được triển khai ở nhiều tầng.

  • Redis thường được sử dụng cho các bài toán counter/rate-limit state.

  • Rate Limiting chỉ là một lớp trong API Security.


FAQ nhanh

API Rate Limiting là gì?

→ Là cơ chế giới hạn số request mà một client được phép gửi trong một khoảng thời gian.

429 là lỗi gì?

429 Too Many Requests, nghĩa là client đã gửi quá nhiều request trong khoảng thời gian được cho phép.

Rate Limiting có phải là Authorization không?

→ Không. Authorization quyết định bạn có quyền làm gì; Rate Limiting quyết định bạn được gọi API với tần suất như thế nào.

Có Token hợp lệ thì có bị Rate Limit không?

→ Có. Authentication thành công không đồng nghĩa với việc bạn được gọi API không giới hạn.

Rate Limiting có chống được DDoS không?

→ Nó có thể giúp giảm hoặc kiểm soát một số dạng lưu lượng quá mức, nhưng không phải giải pháp đầy đủ để chống DDoS. Hệ thống lớn thường cần nhiều lớp bảo vệ khác.

Có nên đặt Rate Limit càng cao càng tốt không?

→ Không. Quá cao thì mất tác dụng bảo vệ; quá thấp thì user bình thường cũng bị 429.

Frontend có thể gây 429 không?

→ Có. Một bug khiến Frontend gọi API lặp liên tục là nguyên nhân khá thực tế.

Khi gặp 429 có nên gọi lại ngay không?

→ Không nên. Hãy kiểm tra Retry-After nếu có và sử dụng chiến lược retry/backoff phù hợp.


Bạn có thể cũng đang gặp 😭

👉 API Authentication là gì? 

👉 Authorization là gì? 

👉 API Pagination là gì?

👉 REST API là gì? 

👉 JSON là gì? 

👉 API là gì? (Giải thích như gọi đồ ăn.)

👉 HTTP vs HTTPS là gì? 

👉 Cookie là gì? 

👉 Session vs Cookie - Hai anh em dễ nhầm nhất của PHP

👉 CRUD là gì? 

👉 SQL Injection là gì?

👉 Prepared Statement là gì?


Tổng kết

Đến đây chúng ta đã có một chuỗi rất thú vị:

Authentication
      ↓
"Anh là ai?"
      ↓
Authorization
      ↓
"Anh được phép làm gì?"
      ↓
Pagination
      ↓
"Anh cần bao nhiêu dữ liệu?"
      ↓
Rate Limiting
      ↓
"Anh gọi bao nhiêu lần?"

😎

Đây là tư duy Backend rất quan trọng.

Một API tốt không chỉ:

"Có dữ liệu là trả dữ liệu."

Mà phải suy nghĩ:

Ai đang gọi?

Người đó có quyền không?

Cần trả bao nhiêu dữ liệu?

Được gọi bao nhiêu lần?

Nếu gọi quá nhanh thì sao?

Nếu Client bị lỗi thì sao?

Nếu có 100 người cùng gọi thì sao?

Nếu có 100.000 người thì sao?

Đó là lúc chúng ta bắt đầu chuyển từ:

"Code chạy được."

sang:

"Code chạy được trong thế giới thật." 😎

Và đó mới là điều DatVietLapTrinh đang muốn hướng tới.