Bạn có 3 bảng users, tasks, comments. Mỗi lần load user profile phải JOIN 3 table, latency 50ms. DynamoDB single-table design gom tất cả vào 1 bảng, 1 query lấy hết – latency 5ms.

Thay vì 3 table users, tasks, comments, single-table lưu tất cả trong 1 table. Lý do: DynamoDB tối ưu cho single-table query: 1 request = 1 partition = tất cả data liên quan.

PK: USER#alice SK: PROFILE#main name, email PK: USER#alice SK: TASK#2026-06-21T08:00 title, status PK: USER#alice SK: TASK#2026-06-20T15:00 title, status PK: TASK#001 SK: COMMENT#2026-06-21T09 text, author

1 query PK=USER#alice lấy tất cả: profile + mọi tasks. Task lưu dưới PK=USER#id nên cần 2 query riêng: 1 query PK=USER#alice, SK=bắt đầu TASK# lấy task, và 1 query PK=TASK#001 lấy comments.

Access-pattern-first design

  1. Get user profile → PK: USER#id, SK: PROFILE#main
  2. List tasks by user → PK: USER#id, SK: begins_with TASK#
  3. Get task → PK: USER#id, SK: TASK#taskId (hoặc dùng GSI)
  4. List comments → PK: TASK#taskId, SK: begins_with COMMENT#
  5. List tasks by status (admin) → GSI1 PK: STATUS#pending, SK: createdAt
  6. Tasks due today → GSI1 PK: DUEDATE#2026-06-21, SK: USER#id

GSI Overload: một index cho nhiều pattern

Cùng GSI1, khác prefix → phục vụ nhiều access pattern:

// Pattern 5: tasks by status
GSI1PK: "STATUS#pending", GSI1SK: "2026-06-21T08:00:00Z"

// Pattern 6: tasks due today
GSI1PK: "DUEDATE#2026-06-21", GSI1SK: "USER#alice"

// Cùng GSI1, query với prefix khác nhau
await ddb.send(new QueryCommand({
  TableName: "myapp", IndexName: "GSI1",
  KeyConditionExpression: "GSI1PK = :pk",
  ExpressionAttributeValues: { ":pk": "STATUS#pending" },
}));

GSI Overload dùng prefix khác nhau trên cùng GSI1PK để phục vụ nhiều access pattern, tiết kiệm WCU  đơn giản hóa code.

## Sparse Index  DAX

Item không cần GSI  không set GSI key  không tốn GSI capacity. DAX = in-memory cache cho DynamoDB, latency từ ~10ms  <1ms cho read.

Bài sau: [Phần 42: Serverless nâng cao -- event-driven patterns](/posts/aws/42-serverless-nang-cao-event-driven-patterns/)