AWS Documentation · Tiếng Việt

Amazon DynamoDB

Cơ sở dữ liệu NoSQL key-value và document, hiệu năng mili-giây ở mọi quy mô — Tài liệu toàn diện từ kiến trúc đến vận hành

Cập nhật 04/2026
Database · NoSQL
AWS Core Service
01 · Tổng quan

DynamoDB là gì?

Amazon DynamoDB là dịch vụ cơ sở dữ liệu NoSQL được quản lý hoàn toàn (fully managed) bởi AWS, hỗ trợ mô hình dữ liệu key-valuedocument. DynamoDB cung cấp hiệu năng ổn định ở mức mili-giây đơn (single-digit millisecond) bất kể quy mô dữ liệu, với khả năng tự động mở rộng (auto scaling) để xử lý hàng triệu request mỗi giây.

Hiệu năng mili-giây
Độ trễ đọc/ghi ổn định dưới 10ms ở mọi quy mô. Hỗ trợ hàng triệu request/giây.
🔧
Fully Managed
Không cần quản lý server, patching, backup. AWS lo toàn bộ hạ tầng.
📈
Auto Scaling
Tự động điều chỉnh throughput theo tải thực tế. Hỗ trợ On-Demand mode.
🌍
Global Tables
Replication đa vùng (multi-region) active-active với độ trễ thấp.
🔐
Bảo mật toàn diện
Encryption at rest (KMS), IAM fine-grained access, VPC Endpoints.
🔗
Tích hợp sâu
Lambda triggers, Streams, DAX cache, AppSync, S3 export và nhiều hơn nữa.

Use Cases phổ biến

  • Gaming: Leaderboard, player sessions, game state — yêu cầu latency cực thấp
  • E-commerce: Shopping cart, product catalog, order history
  • IoT: Lưu trữ dữ liệu sensor, telemetry data với throughput cao
  • Social Media: User profiles, feeds, likes, comments
  • Ad Tech: Real-time bidding, click tracking, impression counting
  • Session Management: Lưu session state cho web/mobile applications
  • Serverless Backend: Kết hợp API Gateway + Lambda + DynamoDB

So sánh DynamoDB vs RDS (Relational Database)

Tiêu chí DynamoDB (NoSQL) RDS (SQL)
Mô hình dữ liệu Key-value / Document (schema-less) Relational (schema-based, tables, rows, columns)
Ngôn ngữ truy vấn PartiQL, API-based (GetItem, Query, Scan) SQL (SELECT, JOIN, GROUP BY...)
Scaling Horizontal (tự động, gần như vô hạn) Vertical (scale up instance) + Read Replicas
Hiệu năng Single-digit ms ở mọi quy mô Phụ thuộc vào query complexity & instance size
JOIN Không hỗ trợ (denormalize data) Hỗ trợ đầy đủ
Transactions Có (giới hạn 100 items, 4MB) Có (ACID đầy đủ)
Quản lý Serverless, fully managed Managed nhưng vẫn cần chọn instance type
Chi phí Pay-per-request hoặc provisioned capacity Pay-per-instance (chạy 24/7)
Phù hợp cho High-scale, low-latency, known access patterns Complex queries, ad-hoc reporting, relationships
💡 Khi nào chọn DynamoDB?
Chọn DynamoDB khi bạn cần: hiệu năng ổn định ở quy mô lớn, access patterns đã biết trước, không cần complex JOIN, và muốn serverless/fully managed. Nếu cần ad-hoc queries phức tạp hoặc nhiều relationships → chọn RDS/Aurora.
02 · Kiến trúc

Kiến trúc DynamoDB

DynamoDB tổ chức dữ liệu theo mô hình Tables → Items → Attributes. Mỗi table yêu cầu một Primary Key duy nhất để định danh từng item.

DynamoDB Data Model 📋 Table: Users PK (Partition Key) SK (Sort Key) Attributes USER#001 PROFILE name="Minh", email="minh@ex.com", age=28 USER#001 ORDER#2024-001 total=150000, status="shipped" USER#001 ORDER#2024-002 total=89000, status="pending" USER#002 PROFILE name="Lan", email="lan@ex.com", age=25 USER#002 ORDER#2024-003 total=250000, status="delivered" Partition Key Sort Key Attributes (schema-less)

Các thành phần chính

Table (Bảng)

Là đơn vị tổ chức dữ liệu cao nhất. Mỗi table chứa nhiều items và yêu cầu định nghĩa Primary Key khi tạo. Không giới hạn số lượng items trong table.

Item (Bản ghi)

Tương đương một "row" trong SQL. Mỗi item là một tập hợp các attributes. Kích thước tối đa của một item là 400 KB.

Attribute (Thuộc tính)

Tương đương "column" trong SQL, nhưng DynamoDB là schema-less — mỗi item có thể có các attributes khác nhau (trừ Primary Key bắt buộc). Hỗ trợ các kiểu dữ liệu: String, Number, Binary, Boolean, Null, List, Map, Set.

Primary Key — Chìa khóa chính

DynamoDB hỗ trợ 2 loại Primary Key:

✅ Simple Primary Key (Partition Key only)
  • Chỉ có Partition Key (PK)
  • PK phải unique cho mỗi item
  • Ví dụ: userId = "USER#001"
  • Phù hợp khi mỗi entity chỉ có 1 record
✅ Composite Primary Key (PK + SK)
  • Gồm Partition Key + Sort Key (SK)
  • Tổ hợp PK+SK phải unique
  • Ví dụ: PK=USER#001, SK=ORDER#2024-001
  • Phù hợp cho one-to-many relationships
⚠️ Quan trọng
Partition Key quyết định partition nào sẽ lưu item. Thiết kế PK kém sẽ gây hot partition — một partition nhận quá nhiều traffic trong khi các partition khác rảnh rỗi, dẫn đến throttling.

Cách DynamoDB phân phối dữ liệu

DynamoDB sử dụng consistent hashing trên Partition Key để phân phối items vào các partition vật lý. Mỗi partition có giới hạn:

  • 10 GB dung lượng lưu trữ
  • 3,000 RCU (Read Capacity Units) hoặc 1,000 WCU (Write Capacity Units)

Khi vượt giới hạn, DynamoDB tự động split partition. Tuy nhiên, throughput không được chia đều nếu access pattern không đồng đều.

03 · Capacity Modes

Capacity Modes — Chế độ dung lượng

DynamoDB cung cấp 2 chế độ tính phí và quản lý throughput: ProvisionedOn-Demand. Bạn có thể chuyển đổi giữa 2 mode mỗi 24 giờ.

📊 Provisioned Mode
  • Bạn chỉ định trước số RCU/WCU cần thiết
  • Trả phí theo capacity đã provision (dù dùng hay không)
  • Hỗ trợ Auto Scaling để tự điều chỉnh
  • Có thể mua Reserved Capacity (giảm đến 77%)
  • Phù hợp: traffic ổn định, dự đoán được
🔥 On-Demand Mode
  • Không cần chỉ định capacity trước
  • Trả phí theo số request thực tế (pay-per-request)
  • Tự động scale lên/xuống ngay lập tức
  • Đắt hơn ~6.5x so với Provisioned (per request)
  • Phù hợp: traffic không dự đoán, spiky workloads

RCU & WCU — Cách tính toán

Read Capacity Unit (RCU)

Loại đọc Công thức Ví dụ (item 6 KB, 10 reads/s)
Strongly Consistent Read 1 RCU = 1 read/s cho item ≤ 4 KB
RCU = ⌈item_size / 4KB⌉ × reads/s
⌈6/4⌉ × 10 = 2 × 10 = 20 RCU
Eventually Consistent Read 1 RCU = 2 reads/s cho item ≤ 4 KB
RCU = ⌈item_size / 4KB⌉ × reads/s / 2
⌈6/4⌉ × 10 / 2 = 2 × 5 = 10 RCU
Transactional Read Tốn gấp 2x Strongly Consistent
RCU = ⌈item_size / 4KB⌉ × reads/s × 2
⌈6/4⌉ × 10 × 2 = 2 × 20 = 40 RCU

Write Capacity Unit (WCU)

Loại ghi Công thức Ví dụ (item 2.5 KB, 5 writes/s)
Standard Write 1 WCU = 1 write/s cho item ≤ 1 KB
WCU = ⌈item_size / 1KB⌉ × writes/s
⌈2.5/1⌉ × 5 = 3 × 5 = 15 WCU
Transactional Write Tốn gấp 2x Standard Write
WCU = ⌈item_size / 1KB⌉ × writes/s × 2
⌈2.5/1⌉ × 5 × 2 = 3 × 10 = 30 WCU
💡 Mẹo thi SAA
Đề thi thường cho bài toán tính RCU/WCU. Nhớ: Eventually Consistent = 1/2 RCU, Transactional = 2x. Luôn làm tròn lên (ceiling) khi chia item size.

Auto Scaling (Provisioned Mode)

Khi dùng Provisioned Mode, bạn nên bật Auto Scaling để DynamoDB tự điều chỉnh RCU/WCU dựa trên CloudWatch metrics:

  • Target Utilization: Mức sử dụng mục tiêu (ví dụ: 70%)
  • Minimum Capacity: Giá trị RCU/WCU tối thiểu
  • Maximum Capacity: Giá trị RCU/WCU tối đa

Auto Scaling sử dụng Application Auto Scaling service và tạo CloudWatch alarms tự động. Lưu ý: scale up nhanh (vài phút) nhưng scale down chậm hơn (15 phút cooldown).

⚠️ Burst Capacity
DynamoDB dự trữ 300 giây unused capacity cho mỗi partition. Khi traffic đột ngột tăng, burst capacity sẽ được sử dụng trước khi throttling xảy ra. Tuy nhiên, không nên dựa vào burst capacity cho thiết kế hệ thống.
04 · Secondary Indexes

Secondary Indexes — Chỉ mục phụ

Secondary Indexes cho phép bạn truy vấn dữ liệu theo các attributes khác ngoài Primary Key. DynamoDB hỗ trợ 2 loại: Global Secondary Index (GSI)Local Secondary Index (LSI).

Đặc điểm GSI (Global Secondary Index) LSI (Local Secondary Index)
Partition Key Khác với base table (bất kỳ attribute nào) Giống base table
Sort Key Tùy chọn, bất kỳ attribute nào Bắt buộc, khác với base table SK
Thời điểm tạo Bất kỳ lúc nào (sau khi tạo table) Chỉ khi tạo table (không thể thêm sau)
Giới hạn số lượng 20 GSI / table 5 LSI / table
Consistency Chỉ Eventually Consistent Eventually hoặc Strongly Consistent
Capacity Có RCU/WCU riêng (tách biệt base table) Dùng chung RCU/WCU với base table
Size limit Không giới hạn 10 GB per partition key value
GSI vs LSI — Cách hoạt động 📋 Base Table PK: userId | SK: orderId 🌐 GSI: email-index PK: email | SK: createdAt → PK khác, RCU/WCU riêng 📍 LSI: status-index PK: userId | SK: status → Cùng PK, SK khác, dùng chung RCU

Projections — Chọn attributes cho Index

Khi tạo index, bạn chọn attributes nào sẽ được "project" (copy) vào index:

  • KEYS_ONLY — Chỉ copy Primary Key của base table + index key. Tiết kiệm storage nhất.
  • INCLUDE — Copy thêm một số attributes cụ thể mà bạn chỉ định.
  • ALL — Copy toàn bộ attributes. Tốn storage nhất nhưng không cần fetch lại base table.
💡 Best Practice cho Index
  • Chỉ tạo GSI khi thực sự cần query pattern mới — mỗi GSI tốn thêm WCU khi write
  • Dùng KEYS_ONLY hoặc INCLUDE thay vì ALL để giảm chi phí storage
  • GSI throttling có thể ảnh hưởng base table — đảm bảo GSI có đủ WCU
  • Cân nhắc dùng sparse index: chỉ items có attribute đó mới xuất hiện trong index
05 · DynamoDB Streams

DynamoDB Streams — Change Data Capture

DynamoDB Streams ghi lại mọi thay đổi (insert, update, delete) trên table theo thứ tự thời gian. Dữ liệu stream được lưu giữ trong 24 giờ và có thể được xử lý bởi Lambda, Kinesis, hoặc ứng dụng tùy chỉnh.

DynamoDB Streams → Lambda Trigger 📱 Application PutItem / UpdateItem 🗄️ DynamoDB Table 🔄 Stream Change records (24h) λ Lambda 📊 Analytics Stream records chứa: KEYS_ONLY | NEW_IMAGE | OLD_IMAGE | NEW_AND_OLD_IMAGES

Stream View Types

View Type Nội dung record Use Case
KEYS_ONLY Chỉ Primary Key của item bị thay đổi Trigger nhẹ, chỉ cần biết item nào thay đổi
NEW_IMAGE Toàn bộ item sau khi thay đổi Sync data sang hệ thống khác
OLD_IMAGE Toàn bộ item trước khi thay đổi Audit log, rollback
NEW_AND_OLD_IMAGES Cả trước và sau khi thay đổi So sánh diff, complex event processing

Lambda Trigger với DynamoDB Streams

Đây là pattern phổ biến nhất: Lambda function tự động được invoke khi có thay đổi trong table.

lambda_handler.py — Xử lý DynamoDB Stream event
import json

def lambda_handler(event, context):
    for record in event['Records']:
        event_name = record['eventName']  # INSERT | MODIFY | REMOVE
        
        if event_name == 'INSERT':
            new_item = record['dynamodb']['NewImage']
            print(f"New item created: {json.dumps(new_item)}")
            # Gửi welcome email, sync to Elasticsearch, etc.
            
        elif event_name == 'MODIFY':
            old_item = record['dynamodb']['OldImage']
            new_item = record['dynamodb']['NewImage']
            print(f"Item updated from {old_item} to {new_item}")
            
        elif event_name == 'REMOVE':
            old_item = record['dynamodb']['OldImage']
            print(f"Item deleted: {json.dumps(old_item)}")
    
    return {'statusCode': 200}
💡 Lưu ý về Streams
  • Stream records được lưu giữ 24 giờ rồi tự động xóa
  • Mỗi table chỉ có 1 stream tại một thời điểm
  • Lambda đọc stream theo batch (có thể cấu hình batch size)
  • Đảm bảo Lambda function idempotent vì có thể nhận duplicate records
  • Streams là nền tảng cho Global Tables replication
06 · DAX

DAX — DynamoDB Accelerator

DAX (DynamoDB Accelerator) là dịch vụ in-memory cache được quản lý hoàn toàn, tương thích API với DynamoDB. DAX giảm độ trễ đọc từ mili-giây xuống micro-giây (microseconds) mà không cần thay đổi application logic.

DAX — In-Memory Cache Architecture 📱 Application DAX SDK Client (thay DynamoDB client) 🚀 DAX Cluster Primary Replica Replica Item Cache + Query Cache 🗄️ DynamoDB Tables μs ms Cache Hit Cache Miss

Đặc điểm chính của DAX

Đặc điểmChi tiết
Hiệu năngGiảm latency từ ms → microseconds (đến 10x nhanh hơn)
Tương thích APIChỉ cần đổi DynamoDB client → DAX client, không cần sửa code logic
ClusterTối thiểu 1 node, khuyến nghị 3+ nodes cho HA (multi-AZ)
Cache TTLItem Cache: 5 phút (default), Query Cache: 5 phút (default)
Write-throughWrites đi qua DAX → DynamoDB, cache được cập nhật tự động
EncryptionEncryption at rest (KMS) và in-transit (TLS)
VPCDAX cluster chạy trong VPC của bạn
✅ Khi nào dùng DAX
  • Read-heavy workloads (nhiều GetItem, Query)
  • Cần latency microsecond
  • Dữ liệu đọc lặp lại nhiều (hot keys)
  • Muốn giảm RCU cost trên DynamoDB
❌ Khi nào KHÔNG dùng DAX
  • Write-heavy workloads (DAX không cache writes hiệu quả)
  • Cần Strongly Consistent reads (DAX chỉ hỗ trợ Eventually Consistent)
  • Application không chạy trong VPC
  • Ít read operations hoặc data ít lặp lại
💡 DAX vs ElastiCache
DAX chuyên cho DynamoDB, tương thích API, không cần sửa code nhiều. ElastiCache (Redis/Memcached) là general-purpose cache, linh hoạt hơn nhưng cần tự quản lý cache logic (cache-aside pattern). Nếu chỉ cache DynamoDB → chọn DAX. Nếu cần cache nhiều nguồn → chọn ElastiCache.
07 · Global Tables

Global Tables — Bảng toàn cầu

Global Tables cung cấp khả năng replication đa vùng (multi-region) với mô hình active-active. Bạn có thể đọc và ghi ở bất kỳ region nào, DynamoDB tự động đồng bộ dữ liệu giữa các replica tables.

Global Tables — Multi-Region Active-Active 🇺🇸 us-east-1 Users Table (replica) ✅ Read + Write 🇪🇺 eu-west-1 Users Table (replica) ✅ Read + Write 🇯🇵 ap-northeast-1 Users Table (replica) ✅ Read + Write 🔄 Asynchronous replication (typically < 1 second) Sử dụng DynamoDB Streams + Last Writer Wins cho conflict resolution

Yêu cầu & Đặc điểm

  • Table phải bật DynamoDB Streams (NEW_AND_OLD_IMAGES)
  • Replication là asynchronous — thường dưới 1 giây
  • Conflict resolution: Last Writer Wins (dựa trên timestamp)
  • Mỗi replica table có thể dùng capacity mode riêng (Provisioned hoặc On-Demand)
  • Hỗ trợ encryption at rest với KMS (CMK hoặc AWS-owned key)
  • Có thể thêm/xóa region bất kỳ lúc nào (không downtime)
⚠️ Chi phí Global Tables
Mỗi write sẽ được replicate sang tất cả regions → chi phí WCU tăng theo số regions. Ví dụ: 3 regions = chi phí write gấp ~3x. Replicated WCU (rWCU) được tính riêng và đắt hơn WCU thường 50%.
08 · Backup & Recovery

Backup & Recovery — Sao lưu & Phục hồi

DynamoDB cung cấp nhiều phương thức backup để bảo vệ dữ liệu, từ on-demand backup đến continuous backup với Point-in-Time Recovery.

📸
On-Demand Backup
Tạo full backup bất kỳ lúc nào. Không ảnh hưởng hiệu năng table. Backup được lưu cho đến khi bạn xóa.
⏱️
Point-in-Time Recovery (PITR)
Continuous backup tự động. Restore về bất kỳ thời điểm nào trong 35 ngày gần nhất (chính xác đến giây).
📤
Export to S3
Export dữ liệu table sang S3 (DynamoDB JSON hoặc Amazon Ion). Không tiêu tốn RCU, sử dụng PITR.
📥
Import from S3
Import dữ liệu từ S3 vào DynamoDB table mới. Hỗ trợ CSV, DynamoDB JSON, Amazon Ion.

So sánh các phương thức Backup

Tính năng On-Demand Backup PITR Export to S3
Kích hoạt Thủ công hoặc qua API/CLI Bật 1 lần, tự động continuous Thủ công hoặc scheduled
Retention Vĩnh viễn (cho đến khi xóa) 35 ngày gần nhất Tùy S3 lifecycle policy
Restore Restore sang table mới Restore sang table mới (bất kỳ thời điểm) Import lại từ S3
Ảnh hưởng hiệu năng Không Không Không (dùng PITR snapshot)
Cross-region Có (copy backup sang region khác) Không (chỉ trong cùng region) Có (S3 cross-region)
Chi phí $0.10/GB/tháng (backup storage) $0.20/GB/tháng $0.11/GB (export) + S3 storage
💡 Best Practice
Luôn bật PITR cho production tables — chi phí thấp nhưng bảo vệ khỏi accidental deletes. Dùng Export to S3 khi cần phân tích dữ liệu với Athena, Redshift, hoặc EMR mà không tốn RCU.
09 · Security

Security — Bảo mật

DynamoDB cung cấp nhiều lớp bảo mật từ network level đến data level, tuân thủ các tiêu chuẩn compliance như SOC, PCI DSS, HIPAA, ISO.

IAM — Identity & Access Management

Mọi truy cập DynamoDB đều thông qua IAM. Bạn có thể kiểm soát chi tiết đến từng action và resource:

IAM Policy — Fine-grained access control
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:GetItem",
        "dynamodb:Query"
      ],
      "Resource": "arn:aws:dynamodb:ap-southeast-1:123456789012:table/Users",
      "Condition": {
        "ForAllValues:StringEquals": {
          "dynamodb:LeadingKeys": ["${www.amazon.com:user_id}"]
        },
        "StringEqualsIfExists": {
          "dynamodb:Select": "SPECIFIC_ATTRIBUTES"
        },
        "ForAllValues:StringEquals": {
          "dynamodb:Attributes": ["userId", "name", "email"]
        }
      }
    }
  ]
}

Fine-Grained Access Control

DynamoDB hỗ trợ condition keys đặc biệt trong IAM policy:

  • dynamodb:LeadingKeys — Giới hạn truy cập theo Partition Key (user chỉ đọc data của mình)
  • dynamodb:Attributes — Giới hạn attributes nào được đọc/ghi
  • dynamodb:Select — Kiểm soát projection (ALL_ATTRIBUTES, SPECIFIC_ATTRIBUTES...)

Encryption — Mã hóa

LoạiChi tiết
Encryption at Rest Mặc định bật cho tất cả tables. 3 tùy chọn: AWS Owned Key (miễn phí), AWS Managed Key (aws/dynamodb), Customer Managed Key (CMK — bạn quản lý rotation)
Encryption in Transit Mọi kết nối đến DynamoDB đều qua HTTPS/TLS. Không cần cấu hình thêm.

VPC Endpoints

Sử dụng VPC Gateway Endpoint để truy cập DynamoDB từ VPC mà không cần đi qua internet. Traffic đi qua AWS private network, tăng bảo mật và giảm latency.

Tạo VPC Endpoint cho DynamoDB
# Tạo VPC Gateway Endpoint cho DynamoDB
aws ec2 create-vpc-endpoint \
  --vpc-id vpc-0abc123def456 \
  --service-name com.amazonaws.ap-southeast-1.dynamodb \
  --route-table-ids rtb-0abc123def456

# Kiểm tra endpoint
aws ec2 describe-vpc-endpoints \
  --filters "Name=service-name,Values=com.amazonaws.ap-southeast-1.dynamodb"
🔒 Security Checklist
  • ✅ Sử dụng IAM roles thay vì access keys cho EC2/Lambda
  • ✅ Bật CloudTrail để audit mọi API calls đến DynamoDB
  • ✅ Dùng VPC Endpoint cho workloads trong VPC
  • ✅ Áp dụng least privilege — chỉ cấp quyền cần thiết
  • ✅ Dùng Customer Managed Key (CMK) cho dữ liệu nhạy cảm
  • ✅ Bật deletion protection cho production tables
10 · Transactions

DynamoDB Transactions — Giao dịch ACID

DynamoDB Transactions cho phép thực hiện nhiều operations (đọc/ghi) trên nhiều items và tables trong một giao dịch ACID (Atomicity, Consistency, Isolation, Durability). Tất cả operations trong transaction hoặc thành công hết, hoặc thất bại hết.

Hai API chính

📝 TransactWriteItems
  • Tối đa 100 actions trong 1 transaction
  • Tổng kích thước ≤ 4 MB
  • Hỗ trợ: Put, Update, Delete, ConditionCheck
  • Idempotent với ClientRequestToken
  • Chi phí: 2x WCU so với standard write
📖 TransactGetItems
  • Tối đa 100 actions trong 1 transaction
  • Tổng kích thước ≤ 4 MB
  • Hỗ trợ: Get (read multiple items atomically)
  • Đảm bảo snapshot isolation
  • Chi phí: 2x RCU so với standard read

Ví dụ: Chuyển tiền giữa 2 tài khoản

transfer_money.py — Transaction example
import boto3

dynamodb = boto3.client('dynamodb')

def transfer_money(from_account, to_account, amount):
    """Chuyển tiền atomic: trừ account A, cộng account B"""
    try:
        dynamodb.transact_write_items(
            TransactItems=[
                {
                    'Update': {
                        'TableName': 'Accounts',
                        'Key': {'accountId': {'S': from_account}},
                        'UpdateExpression': 'SET balance = balance - :amount',
                        'ConditionExpression': 'balance >= :amount',
                        'ExpressionAttributeValues': {
                            ':amount': {'N': str(amount)}
                        }
                    }
                },
                {
                    'Update': {
                        'TableName': 'Accounts',
                        'Key': {'accountId': {'S': to_account}},
                        'UpdateExpression': 'SET balance = balance + :amount',
                        'ExpressionAttributeValues': {
                            ':amount': {'N': str(amount)}
                        }
                    }
                },
                {
                    'Put': {
                        'TableName': 'Transactions',
                        'Item': {
                            'txId': {'S': 'TX-2024-001'},
                            'fromAccount': {'S': from_account},
                            'toAccount': {'S': to_account},
                            'amount': {'N': str(amount)},
                            'status': {'S': 'completed'}
                        }
                    }
                }
            ]
        )
        print("Transfer successful!")
    except dynamodb.exceptions.TransactionCanceledException as e:
        print(f"Transfer failed: {e}")
        # Không có partial update — tất cả rollback
⚠️ Giới hạn Transactions
  • Tối đa 100 items per transaction (across tables)
  • Tổng kích thước ≤ 4 MB
  • Không thể target cùng 1 item nhiều lần trong 1 transaction
  • Chi phí gấp 2x so với standard operations
  • Transactions không hỗ trợ trên Global Tables cross-region
  • Nếu bị conflict (item đang bị modify bởi transaction khác) → TransactionConflictException
11 · Troubleshooting

Các lỗi thường gặp

Dưới đây là các vấn đề phổ biến khi làm việc với DynamoDB và cách khắc phục.

1. Throttling — ProvisionedThroughputExceededException

🔥 Nguyên nhân
  • Vượt quá RCU/WCU đã provision
  • Hot partition — một partition nhận quá nhiều traffic
  • GSI không đủ WCU → throttle ngược base table
  • Burst capacity đã hết

Cách khắc phục:

  • Thiết kế Partition Key phân tán đều (high cardinality)
  • Bật Auto Scaling hoặc chuyển sang On-Demand mode
  • Sử dụng exponential backoff trong application code
  • Kiểm tra và tăng WCU cho GSI
  • Dùng DAX để giảm read load

2. Hot Partition

Xảy ra khi một số ít partition key values nhận phần lớn traffic. Ví dụ: dùng date làm PK → tất cả writes trong ngày đổ vào 1 partition.

🔥 Hot Partition Problem Partition A 🔥 95% traffic THROTTLED! Partition B 2% traffic idle ✓ Partition C 2% traffic idle ✓ Partition D 1% traffic idle ✓ Giải pháp: Write sharding Composite PK Random suffix

3. Item Size Exceeded (400 KB limit)

Mỗi item tối đa 400 KB (bao gồm attribute names + values). Cách xử lý:

  • Nén (compress) large attributes trước khi lưu
  • Lưu large objects (images, files) trên S3, chỉ lưu S3 URL trong DynamoDB
  • Tách item thành nhiều items nhỏ hơn (vertical partitioning)

4. Cost Surprises — Chi phí bất ngờ

💸 Nguyên nhân chi phí cao
  • Scan operations: Scan đọc toàn bộ table → tốn rất nhiều RCU
  • On-Demand mode: Đắt hơn 6.5x so với Provisioned nếu traffic ổn định
  • GSI quá nhiều: Mỗi GSI tốn thêm WCU cho mỗi write vào base table
  • Large items: RCU/WCU tính theo item size — items lớn tốn nhiều capacity hơn
  • Global Tables: Replicated writes tốn thêm rWCU ở mỗi region
  • Quên tắt PITR/Streams: Các tính năng phụ cũng có chi phí

5. Các lỗi API thường gặp

ErrorHTTP CodeNguyên nhân & Cách xử lý
ProvisionedThroughputExceededException 400 Vượt RCU/WCU → Exponential backoff, tăng capacity, hoặc chuyển On-Demand
ConditionalCheckFailedException 400 Condition expression không thỏa mãn → Kiểm tra logic condition
ValidationException 400 Request không hợp lệ (sai data type, thiếu key...) → Kiểm tra request format
ResourceNotFoundException 400 Table/Index không tồn tại → Kiểm tra tên table và region
ItemCollectionSizeLimitExceededException 400 Vượt 10 GB cho 1 partition key (khi có LSI) → Redesign data model
InternalServerError 500 Lỗi phía AWS → Retry với exponential backoff
12 · Best Practices

Tips & Best Practices

Thiết kế DynamoDB đúng cách từ đầu sẽ giúp bạn tránh được nhiều vấn đề về hiệu năng và chi phí. Dưới đây là các best practices quan trọng nhất.

1. Single-Table Design

Single-Table Design là pattern phổ biến nhất trong DynamoDB: lưu nhiều entity types (Users, Orders, Products...) trong cùng 1 table, sử dụng composite primary key để phân biệt.

Single-Table Design — Ví dụ E-commerce
┌──────────────────┬─────────────────────┬──────────────────────────────┐
│ PK               │ SK                  │ Attributes                   │
├──────────────────┼─────────────────────┼──────────────────────────────┤
│ USER#001         │ PROFILE             │ name, email, phone           │
│ USER#001         │ ORDER#2024-001      │ total, status, createdAt     │
│ USER#001         │ ORDER#2024-002      │ total, status, createdAt     │
│ USER#001         │ ADDRESS#home        │ street, city, zipCode        │
│ USER#002         │ PROFILE             │ name, email, phone           │
│ USER#002         │ ORDER#2024-003      │ total, status, createdAt     │
│ PRODUCT#A100     │ METADATA            │ name, price, category        │
│ PRODUCT#A100     │ REVIEW#001          │ rating, comment, userId      │
│ PRODUCT#A100     │ REVIEW#002          │ rating, comment, userId      │
└──────────────────┴─────────────────────┴──────────────────────────────┘

Access Patterns:
  → Lấy profile user:     Query PK="USER#001", SK="PROFILE"
  → Lấy tất cả orders:    Query PK="USER#001", SK begins_with("ORDER#")
  → Lấy product + reviews: Query PK="PRODUCT#A100"
✅ Ưu điểm Single-Table
  • Giảm số lượng API calls (1 Query lấy nhiều entity types)
  • Giảm latency (không cần multiple round-trips)
  • Transactions dễ dàng hơn (cùng table)
  • Ít tables = ít quản lý capacity
❌ Nhược điểm Single-Table
  • Phức tạp hơn khi thiết kế và maintain
  • Khó hiểu cho team mới
  • Cần biết trước tất cả access patterns
  • Khó thay đổi access patterns sau này

2. Partition Key Design — Thiết kế khóa phân vùng

Partition Key tốt phải có high cardinality (nhiều giá trị unique) và uniform distribution (traffic phân bố đều).

❌ PK kém✅ PK tốtLý do
status (active/inactive) userId status chỉ có 2 giá trị → hot partition
date (2024-01-15) userId#date Tất cả writes trong ngày đổ vào 1 partition
country (VN, US, JP) orderId Ít giá trị, traffic không đều giữa các nước
deviceType (iOS/Android) deviceId Chỉ 2-3 giá trị → extreme hot partition

Write Sharding — Kỹ thuật phân tán ghi

Khi PK tự nhiên có low cardinality, thêm random suffix hoặc calculated suffix để phân tán:

Write Sharding Example
# Thay vì PK = "2024-01-15" (hot partition)
# Thêm random suffix: PK = "2024-01-15#3"

import random

def get_sharded_pk(date_str, num_shards=10):
    """Tạo sharded partition key"""
    shard = random.randint(0, num_shards - 1)
    return f"{date_str}#{shard}"

# Write: PK sẽ là "2024-01-15#0", "2024-01-15#1", ..., "2024-01-15#9"
# Read: Cần query tất cả 10 shards rồi merge kết quả
pk = get_sharded_pk("2024-01-15")

# Scatter-Gather pattern cho read
def query_all_shards(date_str, num_shards=10):
    results = []
    for shard in range(num_shards):
        pk = f"{date_str}#{shard}"
        items = dynamodb.query(
            TableName='Events',
            KeyConditionExpression='PK = :pk',
            ExpressionAttributeValues={':pk': {'S': pk}}
        )
        results.extend(items['Items'])
    return results

3. Cost Optimization — Tối ưu chi phí

💰
Chọn đúng Capacity Mode
Traffic ổn định → Provisioned + Auto Scaling + Reserved Capacity (tiết kiệm đến 77%). Traffic spiky → On-Demand.
📉
Giảm Item Size
Dùng tên attribute ngắn (pk thay vì partitionKey). Nén large values. Lưu binary data trên S3.
🎯
Tránh Scan
Scan đọc toàn bộ table → cực tốn RCU. Luôn dùng Query với PK. Tạo GSI nếu cần access pattern mới.
📊
Monitor với CloudWatch
Theo dõi ConsumedReadCapacityUnits, ThrottledRequests, SystemErrors. Set alarms cho anomalies.
🗑️
TTL — Time to Live
Bật TTL để tự động xóa expired items (sessions, logs). Không tốn WCU khi xóa bằng TTL.
📇
Tối ưu GSI
Dùng sparse index, KEYS_ONLY projection. Xóa GSI không dùng. Mỗi GSI = thêm chi phí write.

4. Các Pattern quan trọng khác

  • Optimistic Locking: Dùng ConditionExpression với version number để tránh concurrent update conflicts
  • TTL (Time to Live): Set attribute chứa epoch timestamp → DynamoDB tự xóa item khi hết hạn (miễn phí, không tốn WCU)
  • Sparse Index: Chỉ items có attribute được index mới xuất hiện trong GSI → tiết kiệm storage và RCU
  • Adjacency List: Dùng PK + SK để model graph relationships (many-to-many)
  • Composite Sort Key: Kết hợp nhiều attributes vào SK: STATUS#SHIPPED#2024-01-15 → hỗ trợ begins_with queries
💡 Quy tắc vàng
Xác định access patterns TRƯỚC khi thiết kế table. DynamoDB không phải SQL — bạn không thể query linh hoạt sau khi đã tạo table. Liệt kê tất cả queries cần thiết, rồi thiết kế PK, SK, và GSI để phục vụ từng query.
13 · CLI Cheat Sheet

AWS CLI Cheat Sheet — DynamoDB

Tổng hợp các lệnh AWS CLI thường dùng nhất khi làm việc với DynamoDB.

Quản lý Table

Table Management
# Tạo table với Composite Primary Key (Provisioned mode)
aws dynamodb create-table \
  --table-name Users \
  --attribute-definitions \
    AttributeName=PK,AttributeType=S \
    AttributeName=SK,AttributeType=S \
  --key-schema \
    AttributeName=PK,KeyType=HASH \
    AttributeName=SK,KeyType=RANGE \
  --billing-mode PROVISIONED \
  --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5

# Tạo table On-Demand mode
aws dynamodb create-table \
  --table-name Events \
  --attribute-definitions AttributeName=eventId,AttributeType=S \
  --key-schema AttributeName=eventId,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST

# Liệt kê tables
aws dynamodb list-tables

# Xem thông tin table
aws dynamodb describe-table --table-name Users

# Xóa table
aws dynamodb delete-table --table-name Users

# Chuyển đổi capacity mode
aws dynamodb update-table \
  --table-name Users \
  --billing-mode PAY_PER_REQUEST

CRUD Operations

CRUD — Create, Read, Update, Delete
# PutItem — Tạo/ghi đè item
aws dynamodb put-item \
  --table-name Users \
  --item '{
    "PK": {"S": "USER#001"},
    "SK": {"S": "PROFILE"},
    "name": {"S": "Nguyen Van Minh"},
    "email": {"S": "minh@example.com"},
    "age": {"N": "28"}
  }'

# GetItem — Đọc 1 item (Strongly Consistent)
aws dynamodb get-item \
  --table-name Users \
  --key '{"PK": {"S": "USER#001"}, "SK": {"S": "PROFILE"}}' \
  --consistent-read

# UpdateItem — Cập nhật attributes
aws dynamodb update-item \
  --table-name Users \
  --key '{"PK": {"S": "USER#001"}, "SK": {"S": "PROFILE"}}' \
  --update-expression "SET age = :newAge, updatedAt = :now" \
  --expression-attribute-values '{
    ":newAge": {"N": "29"},
    ":now": {"S": "2024-01-15T10:30:00Z"}
  }'

# DeleteItem — Xóa item
aws dynamodb delete-item \
  --table-name Users \
  --key '{"PK": {"S": "USER#001"}, "SK": {"S": "PROFILE"}}'

# Conditional Write — Chỉ ghi nếu điều kiện thỏa mãn
aws dynamodb put-item \
  --table-name Users \
  --item '{"PK": {"S": "USER#003"}, "SK": {"S": "PROFILE"}, "name": {"S": "Test"}}' \
  --condition-expression "attribute_not_exists(PK)"

Query & Scan

Query & Scan Operations
# Query — Lấy tất cả items của 1 user
aws dynamodb query \
  --table-name Users \
  --key-condition-expression "PK = :pk" \
  --expression-attribute-values '{":pk": {"S": "USER#001"}}'

# Query — Lấy orders của user (SK begins_with)
aws dynamodb query \
  --table-name Users \
  --key-condition-expression "PK = :pk AND begins_with(SK, :sk)" \
  --expression-attribute-values '{
    ":pk": {"S": "USER#001"},
    ":sk": {"S": "ORDER#"}
  }'

# Query với filter (filter sau khi đọc, vẫn tốn RCU)
aws dynamodb query \
  --table-name Users \
  --key-condition-expression "PK = :pk AND begins_with(SK, :sk)" \
  --filter-expression "total > :minTotal" \
  --expression-attribute-values '{
    ":pk": {"S": "USER#001"},
    ":sk": {"S": "ORDER#"},
    ":minTotal": {"N": "100000"}
  }'

# Query trên GSI
aws dynamodb query \
  --table-name Users \
  --index-name email-index \
  --key-condition-expression "email = :email" \
  --expression-attribute-values '{":email": {"S": "minh@example.com"}}'

# Scan — Đọc toàn bộ table (TRÁNH dùng trong production!)
aws dynamodb scan --table-name Users --max-items 10

# Scan với filter
aws dynamodb scan \
  --table-name Users \
  --filter-expression "age > :minAge" \
  --expression-attribute-values '{":minAge": {"N": "25"}}'

Batch Operations

Batch Read & Write
# BatchWriteItem — Ghi nhiều items (tối đa 25 items, 16 MB)
aws dynamodb batch-write-item --request-items '{
  "Users": [
    {
      "PutRequest": {
        "Item": {
          "PK": {"S": "USER#010"},
          "SK": {"S": "PROFILE"},
          "name": {"S": "User 10"}
        }
      }
    },
    {
      "DeleteRequest": {
        "Key": {
          "PK": {"S": "USER#005"},
          "SK": {"S": "PROFILE"}
        }
      }
    }
  ]
}'

# BatchGetItem — Đọc nhiều items (tối đa 100 items, 16 MB)
aws dynamodb batch-get-item --request-items '{
  "Users": {
    "Keys": [
      {"PK": {"S": "USER#001"}, "SK": {"S": "PROFILE"}},
      {"PK": {"S": "USER#002"}, "SK": {"S": "PROFILE"}}
    ],
    "ProjectionExpression": "PK, #n, email",
    "ExpressionAttributeNames": {"#n": "name"}
  }
}'

Backup, Streams & TTL

Backup, Streams, TTL, GSI
# Bật Point-in-Time Recovery
aws dynamodb update-continuous-backups \
  --table-name Users \
  --point-in-time-recovery-specification PointInTimeRecoveryEnabled=true

# Tạo On-Demand Backup
aws dynamodb create-backup \
  --table-name Users \
  --backup-name users-backup-2024-01-15

# Bật DynamoDB Streams
aws dynamodb update-table \
  --table-name Users \
  --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES

# Bật TTL
aws dynamodb update-time-to-live \
  --table-name Sessions \
  --time-to-live-specification Enabled=true,AttributeName=expiresAt

# Tạo GSI
aws dynamodb update-table \
  --table-name Users \
  --attribute-definitions AttributeName=email,AttributeType=S \
  --global-secondary-index-updates '[
    {
      "Create": {
        "IndexName": "email-index",
        "KeySchema": [{"AttributeName": "email", "KeyType": "HASH"}],
        "Projection": {"ProjectionType": "ALL"},
        "ProvisionedThroughput": {
          "ReadCapacityUnits": 5,
          "WriteCapacityUnits": 5
        }
      }
    }
  ]'

# Export table to S3
aws dynamodb export-table-to-point-in-time \
  --table-arn arn:aws:dynamodb:ap-southeast-1:123456789012:table/Users \
  --s3-bucket my-dynamodb-exports \
  --s3-prefix users/ \
  --export-format DYNAMODB_JSON
💡 PartiQL — SQL-like syntax
DynamoDB hỗ trợ PartiQL cho những ai quen SQL:
PartiQL — SQL-compatible queries
# SELECT (Query)
aws dynamodb execute-statement \
  --statement "SELECT * FROM Users WHERE PK='USER#001' AND begins_with(SK, 'ORDER#')"

# INSERT
aws dynamodb execute-statement \
  --statement "INSERT INTO Users VALUE {'PK': 'USER#099', 'SK': 'PROFILE', 'name': 'Test User'}"

# UPDATE
aws dynamodb execute-statement \
  --statement "UPDATE Users SET age=30 WHERE PK='USER#001' AND SK='PROFILE'"

# DELETE
aws dynamodb execute-statement \
  --statement "DELETE FROM Users WHERE PK='USER#099' AND SK='PROFILE'"