Bỏ qua

ADR-0001: Dùng Go (thay vì mở rộng NestJS) cho 4 workload performance-critical

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

Bối cảnh

4 nhu cầu phát sinh không phù hợp với NestJS/Node.js single-threaded event loop:

Vấn đề Vì sao NestJS không phù hợp
PDF/QR generation tốn CPU Block event loop, ảnh hưởng toàn bộ request khác trong cùng process
10.000+ WebSocket đồng thời Node.js connection overhead cao hơn nhiều so với goroutine (~1KB RAM/conn)
VNPay IPN cần respond <50ms Event loop có thể bị block bởi tác vụ khác cùng lúc, khó đảm bảo SLA cứng
ClickHouse batch insert nhiều topic Cần xử lý đồng thời hiệu quả, Node.js worker threads phức tạp hơn goroutine+channel

Quyết định

Tạo repo Go riêng với 4 service độc lập (document-worker, availability-engine, analytics-pipeline, webhook-receiver), chạy song song NestJS backend, giao tiếp thuần qua Kafka (xem ADR-0002).

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

  • Worker threads / cluster mode trong NestJS: giữ 1 ngôn ngữ, giảm chi phí học Go, nhưng vẫn không giải quyết được bài toán 10k+ WebSocket connection memory-efficient hay latency cứng <50ms như goroutine — loại.
  • Rust thay Go: performance tương đương hoặc tốt hơn, nhưng learning curve cao hơn đáng kể và hệ sinh thái Kafka/ClickHouse/WebSocket cho Go trưởng thành hơn ở thời điểm quyết định — loại.
  • Serverless function (Lambda-tương-đương) cho PDF/webhook: giảm vận hành server, nhưng không phù hợp cho availability-engine (WebSocket hub cần giữ state kết nối lâu dài) — loại vì không đồng nhất kiến trúc cho cả 4 bucket.

Hệ quả

  • Được: mỗi bucket dùng đúng mô hình concurrency phù hợp (goroutine cho WebSocket, channel+ticker cho batch insert); SLA latency cứng (VNPay IPN) đạt được dễ dàng hơn.
  • Đánh đổi: thêm 1 ngôn ngữ/repo cần maintain riêng (build pipeline, CI, dependency management khác NestJS); team phải hiểu cả 2 hệ sinh thái; payload Kafka phải giữ đồng bộ struct giữa Go (pkg/events) và NestJS (libs/shared/src/constants/kafka-topics.ts) thủ công — không có schema registry chung.

Liên kết

  • Docs liên quan: README.md (mục "Tại sao cần Go services?")
  • ADR liên quan: ADR-0002