VPS 2GB chạy Postgres + Redis + Next.js: tối ưu RAM cho dev solo

Chia sẻ bài viết

Mục lục
TL;DR
  • VPS 2GB chạy được full stack Next.js + Postgres + Redis nếu tune đúng cách.
  • Postgres giảm shared_buffers xuống 256MB, max_connections 20, work_mem 4MB.
  • Redis bật maxmemory 200MB + policy allkeys-lru để không tràn RAM.
  • Next.js chạy PM2 cluster mode 1 instance, NODE_OPTIONS max-old-space-size=512.
  • Bật swap 2GB là cứu cánh khi peak traffic, đừng tin lời ai bảo swap chậm là bỏ.

Dev solo VN hay đối mặt bài toán: muốn chạy full stack production nhưng ngân sách chỉ đủ VPS 2GB tầm 199k/tháng. Nhiều người nghĩ 2GB không đủ chạy Postgres + Redis + Next.js cùng lúc - thực tế là đủ, miễn là tune đúng. Bài này hướng dẫn cấu hình từng service để vắt kiệt mỗi MB RAM.

Default config của Postgres chiếm tới 800MB-1GB RAM ngay khi khởi động, Redis chiếm thêm vài trăm MB, Next.js dev mode ăn 500MB. Chưa kể kernel + systemd + sshd nuốt 200MB. Cộng lại quá 2GB, chắc chắn OOM kill. Cần ép từng config về mức tối thiểu mà vẫn chạy tốt cho 100-500 user/ngày.

Stack chuẩn cho bài này: Next.js 15 production build (không phải dev), Postgres 16, Redis 7, chạy trên Ubuntu 24.04 hoặc AlmaLinux 9. Mọi config dưới đây test thực tế trên Cloud VPS TND 2GB / 1 vCPU.

1. Đo baseline RAM trước khi tune

Trước tiên đo xem hệ thống fresh dùng bao nhiêu RAM:

free -h
# Mong đợi sau khi cài OS:
#               total        used        free      shared  buff/cache   available
# Mem:          1.9Gi       180Mi       1.5Gi        16Mi       240Mi       1.7Gi
# Swap:            0B          0B          0B

# Kiểm tra process top RAM
ps aux --sort=-%mem | head -10

Mục tiêu: sau khi cài đủ Postgres + Redis + Next.js prod, available RAM còn 200-300MB để xử lý burst traffic. Nếu available dưới 100MB là risk OOM cao.

2. Bật swap 2GB - cứu cánh khi peak

Swap không thay thế RAM nhưng cứu khi traffic peak ngắn hạn. Bật 2GB swap:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# Giảm swappiness để chỉ swap khi RAM gần đầy
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

free -h
# Swap:         2.0Gi          0B       2.0Gi

Vm.swappiness=10 nghĩa là kernel chỉ swap khi RAM còn dưới 10%. Tránh setting=60 mặc định làm app chậm vì swap sớm.

3. Cài và tune Postgres 16 cho VPS 2GB

sudo apt update
sudo apt install -y postgresql-16
sudo systemctl enable --now postgresql

sudo nano /etc/postgresql/16/main/postgresql.conf

Sửa các tham số sau (ghi đè default):

# Memory
shared_buffers = 256MB         # default 128MB, tăng cho cache nhỏ
effective_cache_size = 768MB   # RAM available cho OS cache
work_mem = 4MB                 # mỗi query op dùng
maintenance_work_mem = 32MB    # cho VACUUM, CREATE INDEX

# Connection
max_connections = 20           # default 100, dev solo cần 10-20 là đủ

# WAL
wal_buffers = 4MB
checkpoint_completion_target = 0.9
min_wal_size = 80MB
max_wal_size = 1GB

# Background writer
bgwriter_delay = 200ms
bgwriter_lru_maxpages = 100

# Logging - chỉ log slow query
log_min_duration_statement = 1000  # log query >1s
log_statement = 'none'

Restart postgres và kiểm tra:

sudo systemctl restart postgresql
sudo systemctl status postgresql

# RAM sau tune: ~350-400MB thay vì 800MB
ps aux | grep postgres | head -5

4. Cài Redis 7 và set maxmemory limit

sudo apt install -y redis-server
sudo nano /etc/redis/redis.conf

Sửa các config quan trọng:

bind 127.0.0.1
port 6379
maxmemory 200mb
maxmemory-policy allkeys-lru
appendonly no                 # tắt AOF, dùng RDB nhẹ hơn
save 900 1
save 300 10
save 60 10000
tcp-keepalive 60
timeout 300

Maxmemory 200MB + policy allkeys-lru nghĩa là khi Redis đầy 200MB, nó tự evict key cũ nhất theo LRU. Đừng để default noeviction - app sẽ crash khi Redis full.

sudo systemctl restart redis-server
redis-cli ping
# PONG

redis-cli info memory | grep used_memory_human
# used_memory_human:1.2M

5. Build Next.js production và setup PM2

Quan trọng: KHÔNG chạy npm run dev trên prod VPS - hot reload ngốn 800MB-1GB RAM. Phải build standalone rồi serve.

# next.config.js
module.exports = {
  output: 'standalone',
  experimental: {
    serverMinification: true,
  },
}
cd /var/app
npm ci
npm run build

# Standalone output ở .next/standalone/server.js
ls .next/standalone

Cài PM2 và chạy với memory limit:

sudo npm install -g pm2

# ecosystem.config.js
module.exports = {
  apps: [{
    name: 'web',
    script: '.next/standalone/server.js',
    instances: 1,                    # 1 vCPU thì chạy 1 instance
    exec_mode: 'fork',               # cluster mode ngốn RAM hơn
    max_memory_restart: '600M',      # restart khi vượt 600MB
    node_args: '--max-old-space-size=512',
    env: {
      PORT: 3000,
      NODE_ENV: 'production',
      DATABASE_URL: 'postgres://...',
      REDIS_URL: 'redis://127.0.0.1:6379',
    },
  }],
}

pm2 start ecosystem.config.js
pm2 startup
pm2 save

6. Reverse proxy Caddy thay Nginx tiết kiệm RAM

Caddy tự cấp SSL, config ngắn, ngốn 50MB RAM thay vì Nginx 80MB. Cài Caddy:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Sửa /etc/caddy/Caddyfile:

app.com {
    reverse_proxy 127.0.0.1:3000
    encode gzip zstd

    @static {
        path /_next/static/* /images/* /favicon.ico
    }
    header @static Cache-Control "public, max-age=31536000, immutable"
}
sudo systemctl reload caddy
# Caddy auto cấp SSL Let Encrypt trong 30s

7. Kết quả RAM thực tế sau tune

ServiceRAM trước tuneRAM sau tuneTiết kiệm
Postgres850MB380MB470MB
Redis200MB (no limit)150MB cap50MB
Next.js1.1GB (dev)450MB (prod PM2)650MB
Caddy-50MB-
OS + sshd200MB200MB-
Tổng2.35GB (OOM)1.23GB1.12GB

Available RAM còn 700-800MB để buffer cache và burst traffic. Đủ chạy app SaaS small với 500-1000 user/ngày.

8. Connection pooling với PgBouncer (nâng cao)

Postgres mỗi connection ăn 5-10MB RAM. Với max_connections=20 đã giới hạn. Để tiết kiệm hơn, dùng PgBouncer làm pool, app chỉ thấy 100 connection ảo nhưng thực Postgres chỉ mở 10:

sudo apt install -y pgbouncer
sudo nano /etc/pgbouncer/pgbouncer.ini

[databases]
app_prod = host=127.0.0.1 port=5432 dbname=app_prod

[pgbouncer]
listen_addr = 127.0.0.1
listen_port = 6432
pool_mode = transaction
max_client_conn = 100
default_pool_size = 10
reserve_pool_size = 2

App connect tới port 6432 thay vì 5432, PgBouncer pool transaction để reuse connection. RAM Postgres giảm thêm 100MB.

9. Monitor RAM realtime với htop và pm2 monit

sudo apt install -y htop
htop  # F6 sort by MEM%

# Hoặc xem PM2 process
pm2 monit
pm2 list
pm2 logs web --lines 50

Set alert qua Sentry hoặc Uptime Kuma khi RAM available dưới 100MB. Add cron check 5 phút/lần:

*/5 * * * * /usr/bin/free -m | awk 'NR==2 {if ($7 < 100) print "LOW_RAM"}' | xargs -I{} curl -X POST https://hook.example.com/alert

10. Xử lý OOM kill khi vẫn xảy ra

Nếu OOM Killer vẫn kill process (thường là postgres vì RAM cao nhất), check log:

sudo dmesg | grep -i "out of memory"
sudo journalctl -u postgresql --since "1 hour ago" | grep -i killed

# Giảm OOM score của postgres để kernel kill app trước
sudo systemctl edit postgresql
# Thêm:
[Service]
OOMScoreAdjust=-500

Hoặc upgrade lên VPS 4GB - giá tăng từ 199k lên 399k/tháng, nhưng yên tâm hơn. Cloud VPS TND có nút resize 1-click, giữ nguyên IP.

11. Khi nào nên upgrade lên 4GB hoặc 8GB?

  • Available RAM thường xuyên dưới 200MB (theo dõi 1 tuần).
  • Postgres slow query nhiều, work_mem không đủ.
  • Cần chạy thêm Elasticsearch, Meilisearch hoặc Qdrant.
  • Traffic vượt 2000 user/ngày, cần PM2 cluster 2 instance.
  • Background job (Bull/BullMQ) queue dài, worker bị OOM.

12. Checklist hoàn thiện VPS 2GB production

  • Swap 2GB đã bật, swappiness=10.
  • Postgres shared_buffers=256MB, max_connections=20.
  • Redis maxmemory=200MB, policy=allkeys-lru.
  • Next.js standalone build + PM2 fork mode + max-old-space=512.
  • Caddy reverse proxy với gzip + cache static.
  • PgBouncer pool transaction (optional).
  • htop + pm2 monit để theo dõi RAM realtime.
  • Cron alert khi available RAM dưới 100MB.
  • Snapshot VPS hằng ngày để rollback nhanh.
Cloud VPS cho vibe coder

VPS 2GB đủ chạy full stack production từ 199k/tháng

Cloud VPS TND sẵn AlmaLinux 9, Ubuntu 22/24, Debian 12/13. SSD CEPH, snapshot 1-click, backup hằng ngày, network 200Mbps trong nước. Resize CPU/RAM khi cần upgrade, giữ nguyên IP và data.

Xem 8 cấu hình Cloud VPS →

FAQ

VPS 2GB có chạy được Postgres + Redis + Next.js production không?

Chạy được nếu tune đúng. Cần giảm shared_buffers Postgres xuống 256MB, set Redis maxmemory 200MB, dùng Next.js standalone build với PM2 fork mode. Tổng RAM dùng khoảng 1.2GB, còn 800MB buffer.

Nên dùng Nginx hay Caddy cho VPS 2GB?

Caddy hơn vì auto SSL Let Encrypt không cần cron, config ngắn 5 dòng, RAM ít hơn 30MB. Nginx mạnh cho VPS lớn với nhiều site, không cần thiết cho dev solo 1 app.

Có nên dùng Docker cho stack này?

Không khuyến khích với VPS 2GB. Docker daemon ăn thêm 150-200MB RAM. Cài native (apt install) tiết kiệm RAM và start nhanh hơn. Docker chỉ nên dùng từ VPS 4GB trở lên.

PM2 fork mode hay cluster mode tốt hơn cho 1 vCPU?

Fork mode tốt hơn vì 1 vCPU không có lợi gì khi chạy cluster nhiều instance. Cluster ăn thêm RAM cho master process. Chỉ nên cluster khi VPS có 2+ vCPU.

Khi nào nên upgrade lên VPS 4GB?

Khi available RAM thường xuyên dưới 200MB, hoặc cần thêm service như Elasticsearch, hoặc traffic vượt 2000 user/ngày. Upgrade từ 2GB lên 4GB qua nút Resize 1-click trên Cloud VPS TND, giữ IP và data.

Postgres bị OOM kill thì khôi phục thế nào?

Systemd auto restart postgres trong 5 giây nếu config Restart=always. Kiểm tra dmesg để xác nhận OOM. Sau đó giảm thêm shared_buffers hoặc set OOMScoreAdjust=-500 để kernel kill app khác trước, bảo vệ database.

2009
15+ năm vận hành liên tục
10+
tập đoàn lớn tin dùng
100+
doanh nghiệp SMB Việt
30 ngày
đổi key lỗi miễn phí
Phần mềm bản quyền chính hãng chúng tôi cung cấp
Bản quyền chính hãng Hóa đơn VAT đầy đủ Đổi key lỗi 30 ngày Vận hành từ 2009 MST 0200994870 Hotline 0225.999.6666