Webhook = HTTP callback do server chủ động đẩy tới endpoint của khách khi có event (đảo chiều polling).
Kiến trúc gửi tin cậy:
- Event vào queue (Kafka/SQS), worker đọc và POST tới URL khách → tách phát sinh event khỏi việc gửi (gửi có thể chậm/lỗi).
- Retry với exponential backoff + jitter khi nhận non-2xx hoặc timeout (vd 5s, 30s, 5m...). Quá số lần → đẩy vào dead-letter queue + cảnh báo.
- Đảm bảo at-least-least-once → có thể gửi trùng.
Bảo mật:
- HMAC signature: ký payload bằng secret chung, đặt vào header X-Signature; khách verify để biết tin thật từ bạn và không bị sửa.
- Kèm timestamp trong chữ ký để chống replay; reject nếu lệch > vài phút.
- Khuyến nghị khách verify HTTPS + allowlist IP nếu cần.
Phía nhận — chống trùng:
- Mỗi event có event_id duy nhất; consumer lưu id đã xử lý (idempotency) → bỏ qua bản lặp.
- Trả 2xx nhanh rồi xử lý async; xử lý nặng đồng bộ sẽ gây timeout → kích retry vô ích.
Lưu ý: cung cấp log + replay tool cho khách tự gửi lại event lỗi; phân biệt rõ "đã gửi" và "đã được khách xử lý".
A webhook is a server-initiated HTTP callback to a customer's endpoint on an event (the inverse of polling).
Reliable delivery:
- Events go to a queue (Kafka/SQS); a worker reads and POSTs to the customer URL → decouples event creation from delivery (which can be slow/failing).
- Retry with exponential backoff + jitter on non-2xx or timeout (e.g. 5s, 30s, 5m...). After N attempts → push to a dead-letter queue + alert.
- This guarantees at-least-once → duplicates are possible.
Security:
- HMAC signature: sign the payload with a shared secret in X-Signature; the customer verifies authenticity and integrity.
- Include a timestamp in the signature to prevent replay; reject if skew > a few minutes.
- Recommend HTTPS and IP allowlisting if needed.
Receiver — dedup:
- Each event has a unique event_id; the consumer records processed ids (idempotency) → skip duplicates.
- Return 2xx fast, then process async; heavy synchronous work times out → triggers pointless retries.
Note: give customers a log + replay tool to resend failed events; clearly distinguish "delivered" from "processed by the customer".