# ↔️ Scale dọc và scale ngang: chọn hướng nào

By Better Wise

> Sign in to view the full content of this lesson.

Bài trước ta đã chỉ ra nút thắt cổ chai: khi traffic vượt sức chịu của một tài nguyên nào đó, latency tăng rồi app sập. Bài này trả lời câu hỏi ngay sau đó: có hai cách để thêm sức, nâng cấp chính cái máy đang chạy, hoặc thêm nhiều máy giống nó. Mình sẽ kể lại hai đợt traffic tăng vọt và con số thật trên bảng đo, để bạn thấy khi nào chọn hướng nào.

Sau bài này, bạn có thể:

- Phân biệt scale dọc (scale up) và scale ngang (scale out) bằng con số, không chỉ bằng định nghĩa.
- Nêu giới hạn thực tế của từng hướng: trần vật lý, chi phí, độ phức tạp, khả năng chịu lỗi.
- Chọn hướng phù hợp cho một app cụ thể dựa trên nút thắt đang có.
- Biết mốc nào thì nên dừng scale dọc và chuyển sang scale ngang.

## Scale dọc: nâng cấp chính cái máy đó

Scale dọc (vertical scaling, scale up) là thêm vCPU, RAM, đĩa nhanh hơn cho đúng một máy. Code không đổi, kiến trúc không đổi, chỉ đổi cấu hình.

**Ví dụ có số.** Một API chạy trên máy 4 vCPU / 8GB, p95 khoảng 180ms, chịu được 400 RPS. Traffic tăng từ 200 lên 1.600 RPS trong ba tuần. Mình đo sau mỗi lần nâng cấp:

| Cấu hình | RPS chịu được | p95 | Giá/tháng |
| --- | --- | --- | --- |
| 4 vCPU / 8GB | 400 | 180ms | ~60 USD |
| 8 vCPU / 16GB | 750 | 190ms | ~120 USD |
| 16 vCPU / 32GB | 1.250 | 240ms | ~280 USD |

Nhìn cột RPS: gấp đôi tài nguyên chỉ được 1,9 lần, rồi 1,7 lần. Đó là hiệu suất **dưới tuyến tính**. Lý do rất cụ thể: garbage collector phải quét heap lớn hơn, lock contention tăng khi nhiều thread tranh nhau, và một process hiếm khi dùng hết 16 core cho cùng một loại việc. Cột giá thì tăng ngược lại: 4,7 lần tiền cho 4 lần tài nguyên.

**Điểm mạnh.** Nhanh nhất trong mọi cách (thường 5 đến 15 phút, đôi khi chỉ cần reboot). Không sửa code, không lo session, không cần load balancer. Với database, đây gần như là lựa chọn mặc định vì scale ngang cho database rất phức tạp.

**Giới hạn.** Có trần vật lý (máy lớn nhất của cloud chỉ tới một mức nào đó). Giá tăng nhanh hơn tài nguyên. Nâng cấp thường cần downtime ngắn. Và quan trọng nhất: **một máy to vẫn là một điểm chết**. Máy đó reboot là cả app đi theo.

## Scale ngang: thêm nhiều máy giống nhau

Scale ngang (horizontal scaling, scale out) là chạy nhiều instance giống hệt nhau đứng sau load balancer. Vẫn ví dụ trên: thay vì một máy 16 vCPU, dùng 4 máy 4 vCPU, được khoảng 4 × 400 = 1.600 RPS, vừa đủ cho traffic hiện tại và còn chỗ thêm máy thứ 5 khi cần. Chi phí 4 × 60 = 240 USD, rẻ hơn 280 USD của một máy to.

Nhưng có một điều kiện không thể bỏ qua: mỗi instance phải **stateless**, nghĩa là request nào vào máy nào cũng xử lý được, không phụ thuộc vào session trong RAM hay file upload lưu ở đĩa local. Nếu app còn giữ session trong bộ nhớ của từng máy, scale ngang sẽ tạo ra lỗi rất khó chịu: user đăng nhập ở máy A, request sau rơi vào máy B và bị đá ra. Bài sau nói kỹ chỗ lưu session.

**Điểm mạnh.** Không có trần cứng, thêm máy là thêm sức gần như tuyến tính. Chịu lỗi tốt: một máy chết, ba máy còn lại vẫn chạy. Deploy kiểu cuốn chiếu (rolling) không cần downtime.

**Giới hạn, và đây là phần hay bị bỏ qua.** Scale ngang không xóa nút thắt, nó di chuyển nút thắt:

```mermaid
flowchart LR
    LB["⚖️<br/>Load balancer"]
    A1["🖥️<br/>App 1"]
    A2["🖥️<br/>App 2"]
    A3["🖥️<br/>App 3"]
    A4["🖥️<br/>App 4"]
    DB["🗄️<br/>Database 1 máy"]
    LB --> A1
    LB --> A2
    LB --> A3
    LB --> A4
    A1 --> DB
    A2 --> DB
    A3 --> DB
    A4 --> DB
```

Bốn app server cùng đập vào một database. Trước đây database thở được vì chỉ có một app server, giờ nó nhận gấp bốn lần query và connection. Nút thắt chuyển từ tầng app sang tầng dữ liệu. Đây là lý do bài 2.2 tồn tại.

Chi phí ẩn cũng tăng: load balancer, log và metric tập trung, công deploy nhiều instance, thời gian debug lâu hơn vì lỗi có thể chỉ xảy ra trên một máy.

## Bảng so sánh nhanh

| Tiêu chí | Scale dọc | Scale ngang |
| --- | --- | --- |
| Cách làm | Nâng cấu hình một máy | Thêm nhiều máy giống nhau |
| Tốc độ triển khai | Phút, đôi khi cần reboot | Cần sửa kiến trúc trước |
| Hiệu suất khi tăng tài nguyên | Dưới tuyến tính, giảm dần | Gần tuyến tính |
| Trần | Có, theo giới hạn phần cứng | Gần như không |
| Chi phí phần cứng | Tăng nhanh hơn tài nguyên | Tăng tuyến tính |
| Chi phí vận hành | Thấp | Cao hơn (LB, observability) |
| Chịu lỗi | Kém, một điểm chết | Tốt |
| Yêu cầu về code | Không đổi | Phải stateless |

## Chọn hướng nào: thứ tự thực dụng

Mình không tối ưu mọi thứ cùng lúc. Thứ tự mình dùng qua nhiều đợt traffic tăng:

```mermaid
flowchart TD
    Start["🔥<br/>Tải tăng, app chậm"]
    Q1{"Nút thắt là CPU/RAM<br/>của 1 process?"}
    Up["⬆️<br/>Scale dọc"]
    Q2{"Giá còn tăng<br/>tuyến tính?"}
    Fix["🔧<br/>Sửa state<br/>hoặc tầng DB trước"]
    Out["↔️<br/>Scale ngang"]
    Start --> Q1
    Q1 -->|Có| Up
    Q1 -->|Không| Fix
    Up --> Q2
    Q2 -->|Còn| Up
    Q2 -->|Hết| Out
```

Ba mốc cụ thể để quyết định:

1. **Scale dọc trước, tới khoảng gấp 2 đến 4 lần cấu hình hiện tại.** Đây là vùng giá còn tăng gần tuyến tính và code chưa phải sửa gì. Thường đủ để mua vài tuần hoặc vài tháng.
2. **Chuyển sang scale ngang khi giá vượt khoảng 2 đến 3 lần máy nhỏ nhất chạy được, hoặc khi p95 tăng dù CPU chưa đầy.** Lúc đó thêm core không giải quyết được gì nữa.
3. **Với database, scale dọc trước, rồi đọc từ replica.** Đừng nhảy thẳng sang sharding khi chưa đo.

Hai tình huống thật để bạn hình dung:

- **App quản lý đơn hàng nội bộ, 300 nhân viên, đỉnh 50 RPS.** Scale dọc từ 2 lên 4 vCPU là xong. Không cần load balancer, không cần stateless. Thêm máy chỉ làm hệ thống phức tạp vô ích.
- **App bán vé, 20.000 người cùng bấm lúc 20:00 mở bán.** Một máy to không cứu được, vì tải tăng 40 lần trong 10 giây. Cần scale ngang từ trước, cộng thêm rate limiting và hàng đợi cho tác vụ nặng, hai chủ đề của module 3.

## Vài mẹo để không scale sai hướng

- **Đo trước khi scale.** CPU 25% mà latency cao thì thêm CPU là đổ tiền xuống sông. Nút thắt đang ở database, ở lock, hoặc ở một query chậm.
- **Scale dọc để mua thời gian, scale ngang để mua dung lượng.** Một đêm trước sự kiện lớn thì scale dọc là cách duy nhất kịp.
- **Đừng scale ngang khi app còn giữ state trong RAM.** Sửa cái đó trước, nếu không bạn chỉ nhân bản lỗi.
- **Scale ngang nhân bản cả lỗi.** Một instance memory leak chậm, bốn instance leak nhanh gấp bốn và bạn có bốn lần log giống nhau.
- **Luôn giữ ít nhất hai instance** nếu app cần chạy liên tục. Một máy, dù to đến đâu, vẫn là một điểm chết.

## Chốt lại và bước tiếp theo

- Scale dọc: nhanh, đơn giản, không sửa code, nhưng dưới tuyến tính, có trần, và vẫn là một điểm chết.
- Scale ngang: gần tuyến tính, chịu lỗi tốt, nhưng đòi hỏi app stateless và làm chi phí vận hành tăng.
- Scale ngang không xóa nút thắt, nó di chuyển nút thắt, thường là xuống database.
- Thứ tự thực dụng: scale dọc trong vùng giá còn hợp lý, rồi chuyển sang scale ngang khi p95 tăng dù CPU chưa đầy.

Điều kiện tiên quyết của scale ngang là server stateless. Bài sau sẽ đi thẳng vào câu hỏi khó: nếu không giữ session trong RAM thì session lưu ở đâu, và vì sao chọn sai chỗ lưu cũng làm app sập.

Một app chịu 400 RPS trên 4 vCPU. Nâng lên 8 vCPU chỉ được khoảng 750 RPS, vì scale dọc cho hiệu suất _____. Thêm 4 máy giống nhau đứng sau _____ là scale ngang. Scale ngang chỉ hiệu quả khi mỗi server _____, không giữ session trong RAM. Scale ngang không xóa nút thắt, nó _____ nút thắt sang tầng khác. Một máy to vẫn là _____. Với database, hướng an toàn là scale _____ trước rồi mới đọc từ replica.

Front: Scale dọc (scale up) là gì?
Back: Thêm vCPU, RAM, đĩa nhanh hơn cho đúng một máy, không đổi kiến trúc.

Front: Scale ngang (scale out) là gì?
Back: Chạy nhiều instance giống hệt nhau đứng sau load balancer.

Front: Vì sao scale dọc cho hiệu suất dưới tuyến tính?
Back: GC quét heap lớn hơn, lock contention tăng, một process hiếm khi dùng hết số core.

Front: Nhược điểm lớn nhất của scale dọc về độ sẵn sàng là gì?
Back: Một máy to vẫn là một điểm chết, máy reboot là cả app đi theo.

Front: Scale ngang chỉ hiệu quả khi server có tính chất gì?
Back: Stateless: request vào máy nào cũng xử lý được, không phụ thuộc session hay file local.

Front: Scale ngang tác động gì tới nút thắt cổ chai?
Back: Không xóa nút thắt mà di chuyển nó, thường xuống tầng database.

Front: Chi phí phần cứng của scale ngang tăng theo kiểu gì?
Back: Gần tuyến tính, cộng thêm chi phí ẩn: load balancer, log và metric tập trung, công deploy.

Front: Với database nên scale hướng nào trước?
Back: Scale dọc trước, rồi đọc từ replica, trước khi nghĩ tới sharding.

Front: Mốc nào thì nên chuyển từ scale dọc sang scale ngang?
Back: Khi giá vượt khoảng 2 đến 3 lần máy nhỏ nhất, hoặc p95 tăng dù CPU chưa đầy.

Front: Ưu điểm lớn nhất của scale dọc khi traffic tăng đột ngột là gì?
Back: Nhanh nhất, thường vài phút, không phải sửa code, mua được thời gian ngay trong đêm.

Front: Scale ngang nhân bản thêm cái gì ngoài capacity?
Back: Nhân bản cả lỗi: một instance memory leak thành bốn instance cùng leak.

Front: Một app 50 RPS đỉnh cho 300 nhân viên nội bộ nên scale hướng nào?
Back: Scale dọc lên 4 vCPU là đủ, thêm máy chỉ làm hệ thống phức tạp vô ích.

---

## Contents

Part of [🧯 App chịu tải: load balancer, stateless và rate limiting](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting.md)

- **📈 Vì sao app sập và cách scale**
  - [🔍 Nút thắt cổ chai: vì sao app sập khi đông người dùng](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/nut-that-co-chai-khi-dong-nguoi-dung.md)
  - [↔️ Scale dọc và scale ngang: chọn hướng nào](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/scale-doc-va-scale-ngang.md) (sign-in required) — this lesson
  - [🍪 Server stateless và session lưu ở đâu](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/server-stateless-va-noi-luu-session.md)
  - [✅ Checkpoint: nền tảng scale và session](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/checkpoint-nen-tang-scale-va-session.md)
- **⚖️ Load balancer và connection pool**
  - [🔀 Load balancer: chia tải và health check](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/load-balancer-chia-tai-va-health-check.md)
  - [🗄️ Connection pool database: vì sao cạn connection](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/connection-pool-database-can-connection.md)
  - [✅ Checkpoint: load balancer và database](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/checkpoint-load-balancer-va-database.md)
- **🛡️ Rate limiting, hàng đợi và đọc số tải**
  - [🚧 Rate limiting: chặn tải xấu trước khi vào hệ thống](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/rate-limiting-chan-tai-xau-truoc-khi-vao-he-thong.md)
  - [📮 Hàng đợi cho tác vụ nặng: đẩy việc dài ra background](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/hang-doi-cho-tac-vu-nang.md)
  - [📊 Đọc con số tải cơ bản: RPS, latency, p95, error rate](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/doc-con-so-tai-co-ban-rps-latency-p95.md) (premium content)
  - [✅ Checkpoint: phòng thủ và đọc số tải](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/checkpoint-phong-thu-va-doc-so-tai.md) (premium content)
- [Course cheatsheet](https://everwise.study/courses/app-chiu-tai-load-balancer-stateless-va-rate-limiting/cheatsheet.md) (premium content)
