Какие плюсы и минусы использования общей базы данных между двумя сервисами
Что проверяют
Понимаете ли вы, что общая база связывает сервисы сильнее любого API, и можете ли назвать случаи, когда это всё же разумно. Следом обычно спрашивают, как бы вы разделили такую базу, не останавливая прод.
Как отвечать
Плюсы реальны, их стоит признать:
- транзакции: изменения обоих сервисов коммитятся атомарно, без саг и компенсаций;
- JOIN и отчёты: данные рядом, не нужно собирать их из двух API;
- простота старта: одна база, один бэкап, одна история миграций, меньше инфраструктуры.
Минусы проявляются по мере роста:
- связанность по схеме: переименовали колонку в одном сервисе, упал другой. Независимый деплой, ради которого сервисы и делили, пропадает;
- общий ресурс: тяжёлый отчёт одного сервиса съедает CPU и держит блокировки второго. Соединения тоже общие: у PostgreSQL по умолчанию
max_connections = 100, а у каждой реплики каждого Go-сервиса свойpgxpoolсо своимMaxConns; - общая точка отказа: падение базы или миграция с долгой блокировкой кладут оба сервиса сразу;
- размытое владение: непонятно, кто отвечает за таблицу и кто вправе менять её структуру.
Если общая база неизбежна, снижайте связанность: у каждого сервиса своя схема и своя роль с правами только на свои таблицы, чужие данные читаются через представление, миграции живут в репозитории сервиса-владельца (goose, golang-migrate) и идут по схеме expand/contract. Для обмена событиями без распределённых транзакций подойдёт transactional outbox: событие пишется в той же транзакции, отдельный процесс отправляет его в брокер.
Где спотыкаются
Отвечают догмой «общая база это всегда антипаттерн». Для двух сервисов одной команды на старте это нормальный компромисс, если границы владения записаны.
Не считают соединения. Десять реплик с MaxConns: 20 дают 200 подключений и упираются в лимит базы раньше, чем в CPU.
Предлагают разделить базу одним релизом. Реальный путь постепенный: сначала запрет на чужие таблицы, потом API или репликация данных, потом перенос.