Bỏ qua

ADR-0002: Giao tiếp Go ↔ NestJS thuần qua Kafka, không bao giờ gọi HTTP

  • Status: Accepted
  • Date: ~2026-06-27 (backfilled 2026-07-25)
  • Supersedes: —
  • Superseded by: —

Bối cảnh

Với Go service chạy song song NestJS (ADR-0001), cần quyết định kênh giao tiếp. Nếu cho phép Go gọi HTTP trực tiếp vào NestJS (hoặc ngược lại), 2 hệ thống sẽ coupling chặt về availability/latency của nhau — đúng vấn đề mà việc tách Go ra vốn muốn tránh (VNPay IPN cần <50ms, không thể phụ thuộc NestJS đang bận).

Quyết định

Nguyên tắc bất biến: Go service không bao giờ gọi HTTP endpoint của NestJS. Toàn bộ giao tiếp Go ↔ NestJS đi qua Kafka produce/consume. Ngoại lệ duy nhất: availability-engine được đọc trực tiếp PostgreSQL (booking_db, read-only) để check overlap slot — không qua NestJS API.

Lựa chọn khác đã cân nhắc

  • HTTP call trực tiếp khi cần dữ liệu tức thời (vd: analytics-pipeline gọi field-service lấy thêm context): tiện hơn khi cần dữ liệu không có sẵn trong event payload, nhưng tạo coupling đồng bộ giữa 2 hệ thống vốn được tách ra để độc lập về availability — loại; giải pháp đúng là làm event payload đủ giàu thông tin thay vì gọi ngược.
  • gRPC giữa Go và NestJS: giảm overhead so với REST, nhưng vẫn là giao tiếp đồng bộ, không giải quyết vấn đề coupling — loại vì lý do tương tự.

Hệ quả

  • Được: Go service hoàn toàn độc lập về uptime với NestJS — nếu NestJS down, Go vẫn tiếp tục consume/produce Kafka bình thường (trừ dữ liệu cần aggregate về sau); dễ reason về failure mode (chỉ cần theo dõi Kafka broker + Go service, không phải toàn bộ chuỗi HTTP).
  • Đánh đổi: mọi dữ liệu Go cần phải có sẵn trong Kafka event payload hoặc trong booking_db (chỉ availability-engine) — nếu thiếu field, phải sửa NestJS để emit thêm, không thể "tiện tay" gọi API lấy bù; độ trễ dữ liệu eventual-consistent thay vì real-time.

Liên kết

  • Docs liên quan: README.md (mục "Nguyên tắc bất biến"), pkg/events/
  • ADR liên quan: ADR-0001