Hạ tầng10 phút

Gom nhiều app về 1 server: cắt 40% chi phí VPS (playbook thật)

Tôi suýt nâng cấp server. Làm ngược lại cắt 40% hoá đơn


Tôi nuôi 9 con droplet với hoá đơn khoảng $198/tháng. Khi tải tăng, bản năng bảo "mua máy to hơn". Tôi làm ngược lại: gom 9 con về 1 host chung. Kết quả: khoảng $132/tháng — cắt ~33–40%, không giết app nào, con kiếm tiền zero downtime.


Đây là playbook chính xác.


Toán thật: tiết kiệm đến từ đâu


Nhà cung cấp (DigitalOcean, Hetzner, Linode) tính tiền gần như tuyến tính trên $/GB RAM — gần như không giảm giá theo lượng. 8 con 2GB tốn xấp xỉ 1 con 16GB trên giấy. Vậy tiền tiết kiệm đến từ đâu?


  • Headroom lãng phí: mỗi box nhỏ size theo đỉnh của nó, nên ngồi không cả ngày. Đỉnh RAM gộp của tôi là 8.7GB; đỉnh CPU chạm 82% của 8 vCPU nhưng trung bình chỉ 19%. Khoảng cách đỉnh-vs-trung-bình đó chính là thứ bạn ngừng trả khi gộp.
  • Overhead × N: mỗi VM ngốn ~400MB cho OS + Docker + agent trước khi app chạy. 9 box = ~3.6GB overhead trả 9 lần.
  • Gánh vận hành: 9 box = 9 lần vá lỗi, cert, dashboard. Thời gian là tiền.

  • Mẹo cốt lõi: đừng size box chung theo tổng các đỉnh — đỉnh hiếm khi trùng. Size theo đỉnh đồng thời, thấp hơn nhiều.


    Làm an toàn: nhiều app, một host, không đạp nhau


    Cơ chế gọn là một reverse proxy route theo hostname (tôi dùng Kamal + kamal-proxy; Traefik/Caddy tương tự). Mỗi app khai domain, proxy route đúng container, tự lo cert.


    Công thức migrate mỗi app:


  • Trỏ IP host về box chung; **bỏ publish host-port của DB** (app gọi DB qua tên container trên Docker network — tránh đụng port).
  • Thêm **cap tài nguyên** mỗi container để một app phát rồ không kéo sập cả nhà.
  • pg_dump → restore → verify số dòng → đổi DNS → reconcile phần lệch.

  • Cạm bẫy thật: custom Docker network không tự tạo (phải `docker network create` trước); build remote dùng git committed (code chưa commit âm thầm không deploy).


    Chuyển data zero-loss


    Postgres thì dễ: `pg_dump -Fc` → restore → đối chiếu số dòng trước khi cutover. ClickHouse (event lỗi) thì dùng export native theo bảng, và phải DROP materialized view trước khi load (không thì đếm đôi), cùng override cap RAM mỗi query. Verify bằng anti-join theo id.


    Bảo vệ con kiếm tiền


    Trên box chung, một container không cap là khẩu súng lên đạn — một rò RAM có thể OOM cả máy. Cap cứng RAM/CPU mỗi container biến "mọi thứ chết" thành "con phá phách chết một mình". Giữ sản phẩm trả-tiền cap rộng nhất, hoặc cho nó làm chính cái host.


    Vận hành sau đó


  • Monitoring per-container: node-exporter + cAdvisor + Prometheus + Grafana (gần free). Gotcha: cgroup v2 cần cAdvisor v0.52.1 + mount /sys/fs/cgroup, không thì label tên container rỗng.
  • Alert: cron 5 phút, ≥2 vi phạm liên tiếp + cooldown để khỏi báo giả.
  • Chặn đốt bandwidth: egress đắt hơn storage nhiều. Rate-limit + signed URL + CDN + dời blob sang object storage zero-egress (R2).

  • Học toàn bộ playbook


    Tôi dạy chi tiết từng bước — kèm những lần suýt mất data — trong khóa Tôi tưởng phải NÂNG CẤP server. Hoá ra làm ngược lại — và tiết kiệm 40% (bản tiếng Anh: I thought I had to upgrade my servers).


    Nếu bạn đang nuôi nhiều side project và đốt tiền hosting mỗi tháng, đây là cách cắt nó xuống mà không hy sinh app nào.

    Sẵn sàng tạo khóa học?

    Bắt đầu miễn phí trên CoachHubs.

    Đăng ký miễn phí