Vấn đề: mạng timeout khiến client không biết request đã thành công chưa → retry → tạo double charge / double order. POST vốn không idempotent.
Idempotency key: client sinh một key duy nhất (UUID) cho mỗi ý định nghiệp vụ và gửi qua header Idempotency-Key. Server:
1. Khi nhận request, lưu key + kết quả vào store (Redis/DB) trong một transaction.
2. Nếu key đã tồn tại → trả về kết quả đã lưu, không thực thi lại side-effect.
3. Nếu key mới → thực thi, lưu response, gắn TTL (Stripe giữ 24h).
INSERT INTO idem (key, status) VALUES ($1, 'in_progress')
ON CONFLICT (key) DO NOTHING; -- 0 rows ⇒ đã có ⇒ trả cachedLưu ý:
- Xử lý request đang chạy dở (in_progress): retry trong lúc bản gốc chưa xong → trả 409 hoặc chờ.
- Key phải gắn với nội dung request; cùng key nhưng body khác ⇒ trả lỗi để tránh nhầm.
- Khác với việc API tự nhiên idempotent (PUT/DELETE) — đây là idempotency được áp đặt cho thao tác có side-effect.