Представьте: ваш интернет-магазин на RDS начинает тормозить в пики, а вы переплачиваете за простаивающие ресурсы. Serverless базы данных решают эту проблему — они автоматически масштабируются до нуля при простое и тарифицируются по потреблению. Но неправильное проектирование схемы сведёт экономию на нет: например, частые сканирования в DynamoDB могут обойтись дороже фиксированной инфраструктуры. Мы настраиваем serverless БД для высоконагруженных проектов: DynamoDB, PlanetScale и Neon. С 5+ годами опыта в serverless архитектурах мы внедрили решения для 50+ проектов — от e-commerce до IoT.
Согласно документации AWS, корректное применение Single-Table Design снижает количество операций чтения до 90%.
Почему стоит выбрать serverless базу данных?
Serverless БД устраняют необходимость управления инфраструктурой. Вы не платите за простаивающие ресурсы, а масштабирование происходит автоматически. Для проектов с неравномерной нагрузкой это снижает стоимость инфраструктуры на 35–40%. Однако неправильное проектирование схемы может свести на нет все преимущества: например, частые сканирования в DynamoDB приведут к высоким расходам.
Сравнение вариантов
| БД | Тип | Масштаб | Лучший сценарий |
|---|---|---|---|
| DynamoDB | Key-value / Document | Безлимитный | Высокая нагрузка, предсказуемые запросы |
| PlanetScale | MySQL-compatible | До терабайт | Реляционные данные, GitHub-style branching |
| Neon | PostgreSQL | Малый-средний | Полный SQL, dev environments |
| FaunaDB | Document / Relational | Средний | Мультирегиональная согласованность |
| Upstash | Redis | Малый-средний | Кеш, очереди, rate limiting |
DynamoDB: проектирование под serverless
DynamoDB требует думать о доступе к данным до проектирования схемы. Плохо спроектированная таблица — дорогая и медленная. Единственный правильный подход — Single-Table Design, когда весь домен хранится в одной таблице, а PK/SK кодируют тип сущности:
# Схема для e-commerce
# PK | SK | Данные
# USER#u123 | PROFILE | {name, email}
# USER#u123 | ORDER#o456 | {status, total, items}
# USER#u123 | ORDER#o789 | {status, total, items}
# ORDER#o456 | ITEM#i001 | {product_id, qty, price}
# PRODUCT#p001 | METADATA | {title, description}
import boto3
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('ecommerce')
def get_user_with_orders(user_id: str) -> dict:
response = table.query(
KeyConditionExpression=Key('PK').eq(f'USER#{user_id}') &
Key('SK').begins_with('ORDER#')
)
return response['Items']
def put_order(user_id: str, order: dict):
with table.batch_writer() as batch:
batch.put_item(Item={
'PK': f'USER#{user_id}',
'SK': f'ORDER#{order["id"]}',
**order
})
batch.put_item(Item={
'PK': f'ORDER#{order["id"]}',
'SK': 'METADATA',
'GSI1PK': f'STATUS#{order["status"]}',
'GSI1SK': order['created_at'],
**order
})
Global Secondary Index (GSI) — для альтернативных паттернов доступа, например, получить все заказы по статусу.
DynamoDB On-Demand vs Provisioned
On-Demand: платишь за каждый read/write. Нет планирования мощности. Идеально для unpredictable трафика или новых приложений.
Provisioned + Auto Scaling: задаёшь baseline RCU/WCU, автомасштабирование при пиках. Дешевле при предсказуемой нагрузке.
resource "aws_dynamodb_table" "ecommerce" {
name = "ecommerce"
billing_mode = "PAY_PER_REQUEST" # On-demand
hash_key = "PK"
range_key = "SK"
attribute {
name = "PK"
type = "S"
}
attribute {
name = "SK"
type = "S"
}
attribute {
name = "GSI1PK"
type = "S"
}
attribute {
name = "GSI1SK"
type = "S"
}
global_secondary_index {
name = "GSI1"
hash_key = "GSI1PK"
range_key = "GSI1SK"
projection_type = "ALL"
}
ttl {
attribute_name = "expires_at"
enabled = true
}
}
Neon: Serverless PostgreSQL
Neon разделяет compute и storage. Compute масштабируется до нуля при отсутствии активности, storage оплачивается по объёму. Встроенный branching позволяет создавать изолированные окружения за секунды.
import psycopg2
import os
conn = psycopg2.connect(os.environ['DATABASE_URL'])
with conn.cursor() as cur:
cur.execute("SELECT * FROM orders WHERE user_id = %s", (user_id,))
orders = cur.fetchall()
Branching в Neon:
neon branches create --name feature/new-schema --parent main
neon connection-string feature/new-schema
# → postgresql://user:[email protected]/neondb
PlanetScale
MySQL-совместимый сервис с branching workflow, без foreign key constraints (vitess-based). Использует HTTP-протокол, что особенно хорошо для Lambda:
import { connect } from '@planetscale/database'
const conn = connect({
host: process.env.DATABASE_HOST,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD
})
const results = await conn.execute(
'SELECT * FROM orders WHERE user_id = ?',
[userId]
)
Как настроить connection pooling для Lambda: пошаговое руководство
- Определите тип БД: для RDS используйте RDS Proxy, для Neon — встроенный pooler, для PlanetScale — HTTP-протокол уже решает проблему.
- Для PostgreSQL с PgBouncer: разверните PgBouncer рядом с Lambda (например, в VPC), настройте pool_mode = transaction.
- При использовании Prisma: замените прямые подключения на Prisma Accelerate через переменную окружения
DATABASE_URL. - Проверьте количество одновременных соединений: для 100 Lambda-функций потребуется около 20 соединений в пуле.
- Протестируйте cold start: первый запрос после простоя не должен превышать 300 мс.
Connection pooling для Lambda
Lambda создаёт новое соединение при каждом cold start. При 100 concurrent Lambda — 100 соединений. Это убивает PostgreSQL/MySQL. Решения:
| Решение | Описание | Лучше всего для |
|---|---|---|
| RDS Proxy (AWS) | Connection pooler перед RDS, прозрачный | Приложений на RDS |
| PgBouncer | Self-hosted, перед PostgreSQL | Любой PostgreSQL, тонкий тюнинг |
| Neon/PlanetScale | Встроенный pooling | Managed сервисы, Zero config |
| Prisma Accelerate | Pooler + query cache | Stack на Prisma |
Кейс: миграция заказчика с RDS на Neon
Проект: интернет-магазин с сезонными пиками (Черная пятница). База данных — PostgreSQL 13 на RDS. Средняя нагрузка — 2000 запросов/с, в пике — 15 000. RDS не справлялся, приходилось держать избыточные мощности.
Решение: миграция на Neon с PostgreSQL 15. Итоги:
- Стоимость инфраструктуры снизилась на 35% (с 450 000 до 290 000 ₽/мес).
- Cold start (после перерыва) — 200 мс против прежних 2 с на RDS.
- Время индексации новых данных сократилось втрое благодаря параллельным операциям.
- Команда получила возможность создавать ветки для каждого PR, что ускорило разработку.
Что входит в работу
- Проектирование схемы (Single-Table Design для DynamoDB, нормализация для Neon/PlanetScale).
- Настройка connection pooling (RDS Proxy, PgBouncer, встроенный).
- Оптимизация запросов (индексы, GSIs, бенчмарки).
- CI/CD для branching (автоматическое создание веток при пулл-реквестах).
- Документация схемы и инструкции для команды.
- Обучение разработчиков (ваши инженеры смогут самостоятельно вносить изменения).
- Гарантия поддержки в течение 30 дней после сдачи.
Ориентировочные сроки
- DynamoDB single-table design + базовые операции — 3-5 дней.
- Neon / PlanetScale подключение + pooling — 1-2 дня.
- Миграция существующей БД на serverless — 5-14 дней.
Сроки варьируются в зависимости от сложности схемы и объёма данных. Получите консультацию по вашему проекту — свяжитесь с нами для оценки. Мы подберём оптимальное решение и предложим план работ.







