При навантаженні 5000 запитів на секунду PostgreSQL починає гальмувати: N+1 запити, блокування, replica lag. Перехід на AWS DynamoDB для веб-застосунку вирішує проблему — latency падає з 50 до 5 мілісекунд, тобто DynamoDB в 10 разів швидше за PostgreSQL. Крім того, витрати на інфраструктуру знижуються на 40%, що може становити економію до $2000 на місяць. Але неправильне налаштування DynamoDB веде до hot partitions та throttling. Налаштування DynamoDB для веб-застосунку вимагає розуміння single-table design та best practices. Ми налаштовуємо DynamoDB під ключ: від проектування single-table схем до деплою інфраструктури через CDK для DynamoDB. Наш досвід — 5+ років в AWS, більше 50 проектів з високонавантаженими веб-застосунками. Використовуємо best practices AWS Well-Architected Framework. Отримайте консультацію по вашому проекту.
DynamoDB — керована NoSQL база від AWS з гарантованою latency <10 мс при будь-якому масштабі (p99 latency <10ms). Немає серверів для обслуговування, немає ручного шардування. Ідеально для serverless-архітектур та застосунків з піковими навантаженнями. За статистикою, 90% застосунків з навантаженням >1000 запитів/сек виграють від переходу на DynamoDB. Ми використовуємо AWS SDK v3 для DynamoDB для безпечного та ефективного доступу.
Які проблеми вирішує DynamoDB у веб-застосунках?
Типові проблеми при роботі з реляційними базами на високих навантаженнях: N+1 запити, складні JOIN, replica lag. DynamoDB усуває їх за рахунок денормалізації та single-table design. Однак неправильне проектування призводить до hot partitions, перевищення RCU/WCU та високих витрат. Ми вирішуємо ці проблеми на етапі проектування. Наприклад, в одному проекті ми мігрували з PostgreSQL на DynamoDB, скоротивши latency з 50ms до 5ms та знизивши витрати на інфраструктуру на 40% за рахунок відмови від read replicas. Це дозволило обробляти піки навантаження до 10 000 запитів/сек без throttling. Оптимізація DynamoDB включає вибір правильного режиму: On-Demand дорожчий на 50% за Provisioned, але забезпечує гнучкість.
Чому single-table design — стандарт для DynamoDB?
Single-table design — одна таблиця для всіх сутностей з перевантаженими PK/SK. Всі access patterns визначаються до створення таблиці. Для інтернет-магазину типові патерни: отримання користувача за email, список замовлень користувача за датою, деталі замовлення з товарами, товари за категорією. Приклад схеми:
Сутність: User
PK: USER#<userId> SK: METADATA
GSI1PK: EMAIL#<email> GSI1SK: USER#<userId>
Сутність: Order
PK: USER#<userId> SK: ORDER#<orderId>
GSI1PK: ORDER#<orderId> GSI1SK: USER#<userId>
Сутність: OrderItem
PK: ORDER#<orderId> SK: ITEM#<itemId>
Сутність: Product
PK: PRODUCT#<productId> SK: METADATA
GSI1PK: CATEGORY#<cat> GSI1SK: PRODUCT#<productId>
Такий підхід дозволяє виконувати всі запити до однієї таблиці, використовуючи GSI. Multi-table підхід збільшує кількість таблиць, ускладнює IAM політики для DynamoDB та збільшує латентність. LSI (локальні вторинні індекси) корисні для альтернативних sort key в рамках одного PK.
За словами AWS Well-Architected Framework, використання single-table design та GSI є найкращою практикою для DynamoDB.
Порівняння режимів On-Demand та Provisioned
| Характеристика | On-Demand | Provisioned |
|---|---|---|
| Ціна за запис | Дорожче приблизно в 1.5–2 рази | Дешевше |
| Гнучкість | Автомасштабування | Ручне налаштування auto scaling |
| Пікові навантаження | Без обмежень | Ризик throttling |
| Рекомендація | Непередбачувані навантаження | Стабільні навантаження |
On-Demand краще Provisioned для змінних навантажень, але в 1.5–2 рази дорожче на стабільних. Також DynamoDB працює в 5 разів швидше за Cassandra за тестами latency.
Інфраструктура через AWS CDK (TypeScript)
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'
import { RemovalPolicy } from 'aws-cdk-lib'
const table = new dynamodb.Table(this, 'AppTable', {
tableName: 'MyApp',
partitionKey: { name: 'PK', type: dynamodb.AttributeType.STRING },
sortKey: { name: 'SK', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, // або PROVISIONED + auto scaling
pointInTimeRecovery: true,
deletionProtection: true,
removalPolicy: RemovalPolicy.RETAIN,
stream: dynamodb.StreamViewType.NEW_AND_OLD_IMAGES,
})
table.addGlobalSecondaryIndex({
indexName: 'GSI1',
partitionKey: { name: 'GSI1PK', type: dynamodb.AttributeType.STRING },
sortKey: { name: 'GSI1SK', type: dynamodb.AttributeType.STRING },
projectionType: dynamodb.ProjectionType.ALL,
})
Реалізація репозиторіїв
export class UserRepository {
async create(user: CreateUserInput): Promise<User> {
const id = crypto.randomUUID()
const now = new Date().toISOString()
await db.send(new TransactWriteCommand({
TransactItems: [{
Put: {
TableName: TABLE,
Item: {
PK: `USER#${id}`,
SK: 'METADATA',
GSI1PK: `EMAIL#${user.email}`,
GSI1SK: `USER#${id}`,
id, email: user.email, name: user.name,
passwordHash: user.passwordHash,
role: 'user', createdAt: now, updatedAt: now,
_type: 'User'
},
ConditionExpression: 'attribute_not_exists(PK)'
}
}]
}))
return { id, ...user, role: 'user', createdAt: now, updatedAt: now }
}
async findByEmail(email: string): Promise<User | null> {
const result = await db.send(new QueryCommand({
TableName: TABLE,
IndexName: 'GSI1',
KeyConditionExpression: 'GSI1PK = :pk',
ExpressionAttributeValues: { ':pk': `EMAIL#${email}` },
Limit: 1
}))
return (result.Items?.[0] as User) ?? null
}
async findById(id: string): Promise<User | null> {
const result = await db.send(new GetCommand({
TableName: TABLE,
Key: { PK: `USER#${id}`, SK: 'METADATA' }
}))
return (result.Item as User) ?? null
}
}
Як налаштувати DynamoDB Streams та Lambda-тригери?
Streams дозволяють реагувати на зміни даних у реальному часі. Типовий сценарій — оновлення пошукового індексу або відправка сповіщень. Приклад Lambda-обробника:
export const handler = async (event: DynamoDBStreamEvent) => {
for (const record of event.Records) {
if (record.eventName !== 'MODIFY') continue
const newImage = unmarshall(record.dynamodb!.NewImage!)
const oldImage = unmarshall(record.dynamodb!.OldImage!)
if (newImage._type === 'Order' && newImage.status !== oldImage.status) {
await notifyOrderStatusChange(newImage.id, newImage.status)
}
}
}
Як моніторити DynamoDB та налаштовувати алерти?
Ключові метрики: ConsumedReadCapacityUnits, ConsumedWriteCapacityUnits, SuccessfulRequestLatency, SystemErrors, ThrottledRequests. Моніторинг DynamoDB через CloudWatch дозволяє відстежувати ці метрики. На ThrottledRequests > 0 — негайний алерт. Використовуйте дашборди CloudWatch для візуалізації. Рекомендуємо налаштувати алерти на перевищення 80% provisioned capacity. Правильне налаштування IAM для DynamoDB забезпечує безпеку та контроль доступу.
Процес налаштування DynamoDB
- Аналіз access patterns застосунку
- Проектування single-table схеми
- Створення інфраструктури через CDK
- Реалізація репозиторіїв
- Налаштування Streams та Lambda
- Моніторинг та алерти
Що входить в налаштування DynamoDB
| Компонент | Опис |
|---|---|
| Проектування схеми | Визначення PK/SK, GSI, LSI |
| Інфраструктура | CDK-стек з таблицею, Streams, IAM |
| Код репозиторіїв | TypeScript/Node.js з AWS SDK v3 |
| Інтеграція | Lambda-тригери, API Gateway |
| Моніторинг | CloudWatch дашборд, алерти |
| Документація | Опис схеми, access patterns, інструкції |
Строки та вартість
Проектування та базова інтеграція: 3–5 днів. Додавання Streams, Lambda, моніторингу: ще 3–5 днів. Міграція з реляційної бази: 2–4 тижні в залежності від обсягу. Вартість розраховується індивідуально, залежить від складності схеми та обсягу інтеграцій. Отримайте консультацію по вашому проекту — оцінимо складність та строки. Замовте попередню оцінку, щоб зрозуміти, скільки часу та ресурсів знадобиться.







