Vì DB và message broker là hai hệ thống riêng biệt, không nằm chung một transaction.
Bạn ghi vào cả hai trong cùng một hàm, nhưng không có gì đảm bảo cả hai cùng thành công.
// dual write: two systems, no shared transaction
orderRepository.save(order); // committed
broker.publish(orderCreated); // process crashes here -> event lost foreverHai chiều hỏng:
- Ghi DB xong, publish lỗi (broker down, process bị kill): đơn hàng có trong DB nhưng service khác không bao giờ biết.
- Publish trước, commit DB lỗi: consumer nhận sự kiện cho một đơn hàng không tồn tại.
Đổi thứ tự hai lệnh không giải quyết được, chỉ đổi kiểu lỗi. Bọc try/catch rồi retry publish cũng không cứu nổi trường hợp process chết giữa chừng.
Cách xử lý đúng là đưa việc "ghi dữ liệu" và "ghi ý định gửi message" vào cùng một transaction DB, rồi để một tiến trình riêng đọc bảng đó và publish — đó chính là transactional outbox.