При нагрузке 5000 запросов в секунду PostgreSQL начинает тормозить: N+1 запросы, блокировки, replica lag. Переход на DynamoDB решает проблему — latency падает с 50 до 5 миллисекунд, а затраты на инфраструктуру снижаются на 40% за счёт отказа от read replicas. Но неправильная настройка DynamoDB ведёт к hot partitions и throttling. Мы настраиваем DynamoDB под ключ: от проектирования single-table схем до деплоя инфраструктуры через AWS CDK. Наш опыт — 5+ лет в AWS, более 50 проектов с высоконагруженными веб-приложениями. Используем best practices AWS Well-Architected Framework. Получите консультацию по вашему проекту.
DynamoDB — управляемая NoSQL база от AWS с гарантированной latency <10 мс при любом масштабе. Нет серверов для обслуживания, нет ручного шардирования. Идеально для serverless-архитектур и приложений с пиковыми нагрузками. По статистике, 90% приложений с нагрузкой >1000 запросов/сек выигрывают от перехода на 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.
Почему 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-политики и увеличивает латентность. 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 раза дороже на стабильных.
Инфраструктура через 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. На ThrottledRequests > 0 — немедленный алерт. Используйте дашборды CloudWatch для визуализации. Рекомендуем настроить алерты на превышение 80% provisioned capacity.
Процесс настройки 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 недели в зависимости от объёма. Стоимость рассчитывается индивидуально, зависит от сложности схемы и объёма интеграций. Получите консультацию по вашему проекту — оценим сложность и сроки. Закажите предварительную оценку, чтобы понять, сколько времени и ресурсов потребуется.







