При навантаженні 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 тижні в залежності від обсягу. Вартість розраховується індивідуально, залежить від складності схеми та обсягу інтеграцій. Отримайте консультацію по вашому проекту — оцінимо складність та строки. Замовте попередню оцінку, щоб зрозуміти, скільки часу та ресурсів знадобиться.







