Hành Trình Xây Hệ Thống Đạt Độ Chịu Tải Cho 10 Triệu Người Dùng Trên AWS

Khám phá hành trình kiến trúc hệ thống chịu tải cho 10 triệu người dùng trên AWS: từ thiết kế kiến trúc, scaling WebSocket, Kafka, Redis, MongoDB đến

🏗️ Hành Trình Xây Hệ Thống Đạt Độ Chịu Tải Cho 10 Triệu Người Dùng Trên AWS

Từ zero tới production-grade system: một case study thực chiến cho những ai dấn thân vào thế giới kiến trúc hệ thống lớn.

🧠 1. Khởi nguồn: Vì sao cần scale tới 10 triệu người dùng?

Chúng tôi bắt đầu từ một MVP đơn giản: một ứng dụng di động phục vụ người dùng với chức năng giao tiếp thời gian thực, có user profile, phân quyền và dashboard quản lý. Sản phẩm dần phát triển, số lượng người dùng tăng nhanh chóng sau một chiến dịch viral thành công.

Vấn đề lớn nhất: hệ thống hiện tại không chịu nổi hơn 20K người online cùng lúc.

Mục tiêu đặt ra: xây lại hệ thống đủ để phục vụ được 10 triệu người dùng, với ít nhất 1 triệu concurrent user.

⚙️ 2. Kiến trúc ban đầu và những giới hạn

Kiến trúc ban đầu:

  • Backend: Node.js monolith chạy trên 1 EC2 instance
  • Database: MongoDB standalone
  • Redis cho session và cache
  • WebSocket server gắn trực tiếp với Node.js
  • CI/CD: thủ công, dùng scp để deploy
  • Không có Auto Scaling, không có Load Balancer

Các vấn đề:

  • Memory leak và CPU spike khi user online > 15K
  • MongoDB query chậm dần vì không có phân vùng
  • Không có cách nào mở rộng WebSocket horizontally
  • Thời gian deploy lên tới 10 phút, dễ down hệ thống
  • Không có observability (Prometheus, Grafana...)

🏗️ 3. Thiết kế lại kiến trúc hệ thống từ đầu

3.1. Triết lý thiết kế

  • Stateless backend
  • Horizontal scaling
  • Async-first với message queue
  • Event-driven architecture
  • Polyglot persistence (dùng đúng DB cho đúng job)

3.2. Thành phần mới

Thành phầnCông nghệ
API GatewayAWS API Gateway + Lambda
Backend CoreNestJS chạy trên ECS Fargate
Auth ServiceKeycloak + OAuth2
WebSocket GatewayNode.js + Redis Pub/Sub
Database chínhMongoDB Cluster (Sharded)
SearchOpenSearch
Message QueueKafka
Cache & SessionRedis Cluster
File StorageS3
CI/CDGitHub Actions + CodePipeline
ObservabilityPrometheus + Grafana + Loki
Auto ScalingECS + Application Load Balancer
Infrastructure as CodeTerraform

☁️ 4. Sử dụng dịch vụ AWS một cách tối ưu

4.1. ECS Fargate vs EC2

ECS Fargate được chọn cho flexibility – không cần quản lý EC2, tự động scale, tích hợp tốt với VPC.

4.2. MongoDB Cluster

  • Dùng MongoDB Atlas để tránh việc tự vận hành
  • Sharding theo userId – giúp phân tán đều tải

4.3. Redis Cluster

  • Redis được dùng cho:
    • Session storage
    • Rate limiting
    • WebSocket Pub/Sub (đa vùng)

4.4. Kafka trên MSK

  • Xử lý event-driven:
    • Logging
    • Notification
    • Data sync sang ElasticSearch

4.5. CDN và bảo mật

  • Sử dụng CloudFront + WAF cho layer bảo mật đầu tiên
  • AWS Shield chống DDoS

🚀 5. Chiến lược scaling: từ 100K đến 10 triệu user

5.1. WebSocket Scaling

  • Redis Pub/Sub để sync giữa các node
  • Scale theo CPU và số lượng kết nối
  • Load Balancer sticky session giảm reconnect

5.2. API Backend Scaling

  • Stateless → scale vô hạn theo traffic
  • Tối ưu query MongoDB, chỉ trả về dữ liệu cần thiết
  • Dùng DataLoader để tránh n+1

5.3. Database scaling

  • Sharding + index theo các field hay query
  • Background job dọn log, archive data

5.4. CI/CD tối ưu

  • GitHub Actions + CodePipeline:
    • Tự động test, build, scan image
    • Deploy canary trước khi rollout toàn bộ

📊 6. Giám sát & logging: trái tim của hệ thống production

  • Prometheus: metric CPU, RAM, kết nối
  • Grafana: dashboard real-time
  • Loki: logging tập trung
  • Alertmanager: cảnh báo qua Slack + Telegram

🧪 7. Testing: Không phải chỉ unit test là đủ

  • Unit test: 95% coverage cho service quan trọng
  • Integration test: dùng Testcontainers
  • Load test: K6 để test WebSocket và API
  • Chaos Engineering: simulate down Redis, Kafka...

🔁 8. Tối ưu chi phí: Không phải hệ thống mạnh là đắt

  • Spot Instance cho job không cần uptime cao
  • Scale down ban đêm bằng CloudWatch Alarm
  • S3 lifecycle để tự xóa log cũ
  • Compress WebSocket payloads bằng zlib

🧠 9. Những bài học xương máu

  • Đừng scale quá sớm, nhưng hãy chuẩn bị sớm
  • Tránh coupling giữa các service
  • Logging phải dễ truy vấn – log nhiều không bằng log đúng
  • Không có observability = mù lòa khi production lỗi
  • Cứ 2 tuần load test 1 lần – đừng để production là nơi test đầu tiên

🔚 10. Kết luận

Việc xây dựng hệ thống chịu được 10 triệu người dùng không phải là câu chuyện viển vông, nhưng cũng không phải là việc “click vài cái là xong”. Nó là sự kết hợp của tư duy hệ thống, công nghệ phù hợp, và vô số giờ refactor, test, monitor, tối ưu.

Nếu bạn đang trên hành trình tương tự – chúc bạn vững tay lái, kiến trúc vững chắc và đừng quên: log nhiều vào nhé!
Xin chào! Mình là BaoTrongIT – một lập trình viên đam mê chia sẻ kiến thức lập trình, đặc biệt là về JavaScript, Node.js, NestJS, và các công nghệ backend/frontend hiện đại. Trên blog này, mình thường xuyên đăng tải các bài viết thủ thuật, kinh nghiệm thực chiến, ví dụ minh họa dễ hiểu, giúp bạn tiếp cận và hiểu sâu các khái niệm tưởng như phức tạp trong lập trình.