DynamoDB Capacity Modes: Chọn Provisioned hay On-Demand để tránh throttling và tiết kiệm chi phí?

Bạn vừa thiết kế xong schema cho DynamoDB table đầu tiên và đang nhìn chằm chằm vào màn hình console, phân vân giữa hai lựa chọn: Provisioned hay On-Demand. Traffic pattern của ứng dụng chưa rõ ràng, và chọn sai có thể dẫn đến throttling làm gián đoạn dịch vụ hoặc hóa đơn AWS tăng đột biến không kiểm soát được. Bài viết này phân tích cơ chế hoạt động của từng DynamoDB capacity mode, khi nào nên dùng cái nào, và cách chuyển đổi an toàn giữa hai chế độ.

TL;DR — DynamoDB Capacity Modes So Sánh Nhanh

Tiêu chíOn-DemandProvisioned
Traffic patternKhông dự đoán được / mới ra mắtỔn định, có thể dự đoán
Chi phí baselineCao hơn per-requestThấp hơn nếu utilization cao
Throttling riskRất thấp (AWS tự scale)Có nếu provisioned capacity không đủ
Auto ScalingTích hợp sẵn, không cần cấu hìnhCần bật riêng, có độ trễ scale
Phù hợp nhấtSpiky workload, MVP, dev/testProduction workload ổn định

Cơ Chế Hoạt Động của DynamoDB Capacity Modes

Trước khi quyết định, cần hiểu DynamoDB phân bổ capacity như thế nào ở tầng vật lý. Mỗi DynamoDB table được phân tán trên nhiều partition. Capacity — đo bằng Read Capacity Units (RCU) và Write Capacity Units (WCU) — được phân bổ đều cho các partition này. Đây là nguồn gốc của hầu hết các vấn đề throttling trong thực tế.

graph LR Client["Client Application"] --> Router["DynamoDB Router"] Router --> P1["Partition 1
Token Bucket"] Router --> P2["Partition 2
Token Bucket"] Router --> P3["Partition N
Token Bucket"] P1 --> Check1{"Token còn?"} Check1 -->|Yes| OK1["Xử lý Request"] Check1 -->|No| Err1["ThrottlingException"] P2 --> Check2{"Token còn?"} Check2 -->|Yes| OK2["Xử lý Request"] Check2 -->|No| Err2["ThrottlingException"]
  1. Request đến DynamoDB: Client gửi read/write request tới DynamoDB endpoint.
  2. Router xác định partition: DynamoDB router dùng partition key để xác định partition vật lý chứa item.
  3. Capacity check: Partition kiểm tra token bucket của mình — nếu còn token thì xử lý, nếu hết thì trả về ProvisionedThroughputExceededException.
  4. On-Demand vs Provisioned: Ở On-Demand, AWS quản lý token bucket tự động và scale theo traffic. Ở Provisioned, token bucket được nạp theo RCU/WCU bạn đã cấu hình.

Read Capacity Unit và Write Capacity Unit là gì?

Một RCU tương đương một strongly consistent read cho item tối đa 4 KB, hoặc hai eventually consistent reads. Một WCU tương đương một write cho item tối đa 1 KB. Transactional reads/writes tiêu thụ gấp đôi. Đây là đơn vị tính toán nền tảng cho cả hai capacity mode.

On-Demand Mode — Khi Nào Nên Dùng?

On-Demand là lựa chọn mặc định hợp lý cho bất kỳ workload nào chưa có traffic data. AWS tự động phân bổ capacity để đáp ứng request — bạn không cần đặt RCU/WCU thủ công. Chi phí tính theo số request thực tế.

On-Demand giống như taxi: bạn trả tiền cho từng chuyến đi, không cần thuê xe cả tháng. Tiện lợi khi không biết mình sẽ đi bao nhiêu, nhưng đắt hơn nếu bạn đi rất nhiều mỗi ngày.

Tuy nhiên, On-Demand không có nghĩa là không có giới hạn. Mỗi table mới ở On-Demand có throughput limit ban đầu, và limit này tăng dần khi traffic thực tế tăng. Nếu traffic tăng đột ngột vượt quá mức AWS đã quan sát trước đó, vẫn có thể xảy ra throttling tạm thời. Kiểm tra Service Quotas trong AWS documentation để biết giới hạn hiện tại.

Tạo table với On-Demand mode

# Tạo DynamoDB table với On-Demand capacity mode
aws dynamodb create-table \
  --table-name my-ondemand-table \
  --attribute-definitions AttributeName=userId,AttributeType=S \
  --key-schema AttributeName=userId,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-1

Kiểm tra billing mode của table hiện tại

aws dynamodb describe-table \
  --table-name my-ondemand-table \
  --region us-east-1 \
  --query 'Table.BillingModeSummary'

Provisioned Mode — Khi Nào Nên Dùng?

Provisioned capacity phù hợp khi bạn đã có đủ traffic data để dự đoán workload. Bạn đặt trước RCU và WCU, trả tiền theo giờ cho capacity đã đặt — dù có dùng hết hay không. Lợi thế: chi phí thấp hơn đáng kể so với On-Demand nếu utilization cao và ổn định.

Provisioned mode hỗ trợ Auto Scaling — DynamoDB tự động điều chỉnh RCU/WCU trong khoảng min/max bạn định nghĩa dựa trên CloudWatch metrics. Nhưng Auto Scaling có độ trễ phản ứng, không phù hợp với traffic spike đột ngột trong vài giây.

Tạo table với Provisioned mode và Auto Scaling

🔽 Click để xem lệnh tạo Provisioned table
# Bước 1: Tạo table với Provisioned capacity
aws dynamodb create-table \
  --table-name my-provisioned-table \
  --attribute-definitions AttributeName=orderId,AttributeType=S \
  --key-schema AttributeName=orderId,KeyType=HASH \
  --billing-mode PROVISIONED \
  --provisioned-throughput ReadCapacityUnits=100,WriteCapacityUnits=50 \
  --region us-east-1

# Bước 2: Đăng ký table với Application Auto Scaling
aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id table/my-provisioned-table \
  --scalable-dimension dynamodb:table:WriteCapacityUnits \
  --min-capacity 10 \
  --max-capacity 500 \
  --region us-east-1

# Bước 3: Tạo scaling policy
aws application-autoscaling put-scaling-policy \
  --service-namespace dynamodb \
  --resource-id table/my-provisioned-table \
  --scalable-dimension dynamodb:table:WriteCapacityUnits \
  --policy-name WriteAutoScalingPolicy \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration \
    'TargetValue=70.0,PredefinedMetricSpecification={PredefinedMetricType=DynamoDBWriteCapacityUtilization}' \
  --region us-east-1
graph TD Traffic["Traffic Tăng"] --> CW["CloudWatch Metric
WCU Utilization > 70%"] CW --> AS["Application Auto Scaling
Tính capacity mới"] AS --> Update["DynamoDB UpdateTable
Tăng WCU"] Update --> Delay["Propagation Delay
vài phút"] Delay --> NewCap["Capacity Mới Có Hiệu Lực"] NewCap --> Risk["⚠️ Khoảng thời gian này
dễ bị throttling"] style Risk fill:#ff9999,stroke:#cc0000
  1. Traffic tăng: WCU utilization vượt ngưỡng target (ví dụ 70%).
  2. CloudWatch alarm: Application Auto Scaling nhận tín hiệu từ CloudWatch metric.
  3. Scale-out decision: Auto Scaling tính toán capacity mới và gửi lệnh update tới DynamoDB.
  4. Propagation delay: Có độ trễ vài phút trước khi capacity mới có hiệu lực — đây là khoảng thời gian dễ bị throttling nhất.
  5. Scale-in: Khi traffic giảm, Auto Scaling giảm capacity về mức thấp hơn để tiết kiệm chi phí.

Hướng Dẫn Quyết Định: Chọn DynamoDB Capacity Mode Nào?

graph TD Start(["Bắt đầu chọn Capacity Mode"]) --> Q1{"Đã có traffic data
ổn định từ 2+ tuần?"} Q1 -->|Không| Q2{"Workload có spike
đột ngột không?"} Q1 -->|Có| Q3{"Traffic pattern
có thể dự đoán?"} Q2 -->|Có hoặc Không biết| OnDemand["✅ On-Demand
PAY_PER_REQUEST"] Q3 -->|Có| Q4{"Chi phí On-Demand
đang cao?"} Q3 -->|Không| OnDemand Q4 -->|Có| Provisioned["✅ Provisioned
+ Auto Scaling"] Q4 -->|Không| OnDemand style OnDemand fill:#90EE90,stroke:#228B22 style Provisioned fill:#87CEEB,stroke:#4682B4

Quy tắc thực tế: bắt đầu với On-Demand, thu thập CloudWatch metrics trong 2-4 tuần, sau đó đánh giá lại. Nếu traffic ổn định và chi phí On-Demand đang cao, chuyển sang Provisioned với Auto Scaling.

Chuyển Đổi Giữa Hai Capacity Modes

Bạn có thể chuyển đổi giữa On-Demand và Provisioned bất kỳ lúc nào, nhưng có một ràng buộc quan trọng: mỗi table chỉ được phép chuyển đổi một lần trong 24 giờ. Lên kế hoạch kỹ trước khi thực hiện trong production.

Chuyển từ On-Demand sang Provisioned

# Chuyển sang Provisioned — bạn phải chỉ định rõ RCU và WCU mong muốn
aws dynamodb update-table \
  --table-name my-ondemand-table \
  --billing-mode PROVISIONED \
  --provisioned-throughput ReadCapacityUnits=200,WriteCapacityUnits=100 \
  --region us-east-1

Khi chuyển từ On-Demand sang Provisioned, bạn phải chỉ định rõ ràng giá trị RCU và WCU mong muốn. DynamoDB sẽ sử dụng các giá trị bạn cung cấp làm cài đặt capacity ban đầu cho bảng. Dùng CloudWatch metrics từ giai đoạn On-Demand để ước tính giá trị phù hợp — nhìn vào ConsumedReadCapacityUnitsConsumedWriteCapacityUnits tại peak traffic.

Chuyển từ Provisioned sang On-Demand

aws dynamodb update-table \
  --table-name my-provisioned-table \
  --billing-mode PAY_PER_REQUEST \
  --region us-east-1

Chẩn Đoán Throttling — Từ Triệu Chứng Đến Nguyên Nhân Thực Sự

Đây là tình huống xảy ra khá phổ biến: bạn đã bật Auto Scaling, nhìn vào CloudWatch thấy consumed capacity vẫn thấp hơn provisioned capacity, nhưng ứng dụng vẫn báo ProvisionedThroughputExceededException. Chẩn đoán ban đầu thường là 'capacity không đủ' — nhưng đó là sai lầm.

Nguyên nhân thực sự thường là hot partition: một partition key nhận quá nhiều traffic so với các partition khác. Vì capacity được phân bổ đều cho tất cả partition, partition 'nóng' đó bị throttle dù tổng capacity của table vẫn còn dư. Tăng provisioned capacity không giải quyết được vấn đề này — bạn cần phân tích access pattern.

Bước 1: Xác nhận throttling đang xảy ra

Kiểm tra metric SystemErrorsThrottledRequests để xác nhận throttling trước khi đào sâu hơn — đừng bắt đầu thay đổi capacity dựa trên log ứng dụng đơn thuần.

aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name ThrottledRequests \
  --dimensions Name=TableName,Value=my-provisioned-table \
                Name=Operation,Value=PutItem \
  --start-time 2024-01-15T00:00:00Z \
  --end-time 2024-01-15T23:59:59Z \
  --period 300 \
  --statistics Sum \
  --region us-east-1

Bước 2: Kiểm tra consumed capacity theo thời gian thực

So sánh ConsumedWriteCapacityUnits với ProvisionedWriteCapacityUnits để xem utilization thực tế. Nếu consumed thấp hơn provisioned nhiều nhưng vẫn có throttling, đây là dấu hiệu rõ ràng của hot partition — không phải thiếu capacity tổng thể.

aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name ConsumedWriteCapacityUnits \
  --dimensions Name=TableName,Value=my-provisioned-table \
  --start-time 2024-01-15T00:00:00Z \
  --end-time 2024-01-15T23:59:59Z \
  --period 60 \
  --statistics Sum \
  --region us-east-1

Bước 3: Bật Contributor Insights để tìm hot partition key

Khi consumed capacity thấp nhưng throttling vẫn xảy ra, Contributor Insights là công cụ duy nhất cho bạn thấy partition key nào đang bị truy cập nhiều nhất — đây là bước chẩn đoán không thể bỏ qua.

# Bật Contributor Insights để phân tích hot key
aws dynamodb update-contributor-insights \
  --table-name my-provisioned-table \
  --contributor-insights-action ENABLE \
  --region us-east-1

Sau khi bật, vào CloudWatch Contributor Insights để xem top partition keys theo read/write traffic. Nếu một key chiếm hơn 50% traffic, bạn cần redesign partition key strategy — ví dụ thêm random suffix hoặc dùng write sharding.

Bước 4: Kiểm tra Auto Scaling có hoạt động không

Auto Scaling có thể bị disabled hoặc misconfigured mà không có cảnh báo rõ ràng. Bước này đóng khoảng trống mà các bước trên không thể phát hiện — capacity đủ trên giấy nhưng không tự scale khi cần.

aws application-autoscaling describe-scalable-targets \
  --service-namespace dynamodb \
  --resource-ids table/my-provisioned-table \
  --region us-east-1

IAM Permissions Cần Thiết

Để thực hiện các thao tác quản lý capacity mode, IAM principal cần các permissions sau. Áp dụng least privilege — chỉ cấp những gì thực sự cần.

🔽 Click để xem IAM policy mẫu
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DynamoDBCapacityManagement",
      "Effect": "Allow",
      "Action": [
        "dynamodb:CreateTable",
        "dynamodb:UpdateTable",
        "dynamodb:DescribeTable",
        "dynamodb:UpdateContributorInsights",
        "dynamodb:DescribeContributorInsights"
      ],
      "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/my-provisioned-table"
    },
    {
      "Sid": "AutoScalingForDynamoDB",
      "Effect": "Allow",
      "Action": [
        "application-autoscaling:RegisterScalableTarget",
        "application-autoscaling:PutScalingPolicy",
        "application-autoscaling:DescribeScalableTargets",
        "application-autoscaling:DescribeScalingPolicies"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CloudWatchMetricsRead",
      "Effect": "Allow",
      "Action": [
        "cloudwatch:GetMetricStatistics",
        "cloudwatch:DescribeAlarms"
      ],
      "Resource": "*"
    }
  ]
}

Lưu ý: application-autoscalingcloudwatch actions thường yêu cầu "Resource": "*" vì các actions này không hỗ trợ resource-level restriction. Kiểm tra AWS Service Authorization Reference để xác nhận trước khi triển khai.

Wrap-Up: Lựa Chọn DynamoDB Capacity Mode Đúng Cho Production

Nếu bạn chưa có traffic data, bắt đầu với On-Demand — đây là lựa chọn an toàn nhất để tránh throttling trong giai đoạn đầu. Sau 2-4 tuần, phân tích CloudWatch metrics để quyết định có nên chuyển sang Provisioned với Auto Scaling hay không. Đừng bỏ qua bước kiểm tra hot partition — đây là nguyên nhân throttling phổ biến nhất mà tăng capacity không giải quyết được.

Tham khảo thêm: AWS DynamoDB Read/Write Capacity Mode DocumentationDynamoDB Auto Scaling Documentation.

Glossary — Thuật Ngữ Chính

Thuật ngữĐịnh nghĩa
RCU (Read Capacity Unit)Đơn vị đo read throughput: 1 strongly consistent read cho item ≤ 4 KB, hoặc 2 eventually consistent reads.
WCU (Write Capacity Unit)Đơn vị đo write throughput: 1 write cho item ≤ 1 KB.
Hot PartitionPartition nhận traffic không đồng đều cao hơn các partition khác, dẫn đến throttling dù tổng capacity còn dư.
Contributor InsightsTính năng CloudWatch giúp xác định partition keys và sort keys được truy cập nhiều nhất trong DynamoDB table.
Auto ScalingTính năng của Application Auto Scaling tự động điều chỉnh Provisioned RCU/WCU dựa trên CloudWatch utilization metrics.

Nhận xét

Bài đăng phổ biến từ blog này

EC2 Không Có Internet Trong Custom VPC: Cách Gắn Internet Gateway và Cập Nhật Route Table

Route 53 Alias vs CNAME: Khi Nào Dùng Alias Record Cho Zone Apex?