At-most-once (fire-and-forget): producer đặt acks=0, consumer commit offset trước khi xử lý. Message có thể mất nhưng không bao giờ trùng. Hợp với metrics, log — những thứ không cần chính xác tuyệt đối.
At-least-once: producer đặt acks=all kèm retries, consumer commit sau khi xử lý xong. Không mất message, nhưng có thể xử lý trùng nếu consumer chết sau lúc xử lý mà trước lúc commit. Vì vậy logic consumer bắt buộc phải idempotent.
Exactly-once: khó nhất, cần producer và consumer phối hợp.
- Producer: bật enable.idempotence=true và dùng Kafka Transactions (transactional.id).
- Consumer: đặt isolation.level=read_committed, và commit offset trong cùng transaction với business logic — nếu ghi xuống DB thì phải theo pattern transactional outbox.
- Kafka Streams với processing.guarantee=exactly_once_v2 lo trọn gói phần này.
Lưu ý: exactly-once làm latency tăng khoảng 20-30%, nên chỉ dùng cho billing và giao dịch tài chính, đừng bật mặc định cho mọi topic.