Branching БД — Git-подход к данным
Знакомая боль: твой коллега прислал PR с миграцией. Ты хочешь его потестить — но если запустишь миграцию у себя, твоя локальная БД с тестовыми данными уйдёт в кашу. Если тестить на staging — он один на всех, кто-то перезапишет. Решение, которое стало стандартом в 2024-2025: branching БД. Каждая фича получает свою полную копию прод-данных. Меняешь как хочешь. Сливается фича — ветка БД удаляется. Точно как Git, только для данных.
Как branching работает технически
Под капотом — copy-on-write. Когда ты создаёшь ветку, физически данные не копируются. Создаётся метка времени, и обе ветки указывают на один и тот же набор страниц на диске. Когда в одной из веток меняешь данные — затрагиваемые страницы клонируются (только они, не вся БД). Поэтому создание ветки на 50 GB занимает секунду и не стоит места почти ничего. Расходы появляются только когда расходимся в данных. Эту технологию первым запихнул в managed-сервис Neon, теперь повторяют другие.
Use case 1: каждый PR — своя БД
Открыл PR в GitHub → CI создаёт ветку БД из main → запускает миграции из этого PR → деплоит preview-версию приложения с этой веткой → reviewer видит реально работающий сайт с твоими изменениями + production-data. Закрыл PR → ветка БД удалилась. Vercel + Neon сделали это в три клика интеграцией. Раньше «давайте потестим миграцию» = неделя организации, теперь = автоматика.
Use case 2: безопасные эксперименты на проде
Хочешь попробовать опасную миграцию? Создаёшь ветку из main, запускаешь у себя, смотришь сколько займёт, не сломалось ли что. Всё хорошо — катишь на main. Сломалось — удалил ветку, никого не задело. Это огромный сдвиг по безопасности: все изменения сначала пробуются на копии прода, не на самом проде.
Use case 3: разработка с реальными данными
Локальная БД с seed-данными — всегда синтетика. Юзеров 50, реальных edge-cases нет. На прод-копии разработчик видит: реальные имена с эмодзи, контент длиннее лимитов формы, ID-формы которых не предусмотрены. Половина продакшн-багов ловится сразу. Безопасность: маска чувствительных данных (email → fake@test.com) делается одним SQL-скриптом при создании ветки.
Что важно понимать перед использованием
Ветка БД — это ИЗОЛИРОВАННАЯ копия. Изменения в ней НЕ отражаются на main. Это и есть фича. НО: если в main продолжают приходить новые записи (юзеры регистрируются), твоя ветка их не получит — она зафиксирована на момент создания. Долгоживущие ветки = устаревшие данные. Решение: пересоздавать ветку перед каждым новым раундом тестирования. В Neon это команда
# Установка neonctl npm i -g neonctl neonctl auth # один раз — открывает браузер # Создать ветку из main для PR-123 neonctl branches create \ --project-id <project-id> \ --name pr-123 \ --parent main # Получить connection string этой ветки neonctl connection-string pr-123 # postgres://user:pass@ep-xxx-pr-123.aws.neon.tech/db # В .env.preview для этой ветки: # DATABASE_URL=<connection-string-выше> # Запустить миграции на ветке DATABASE_URL=<branch-url> npx prisma migrate deploy # Сбросить ветку к актуальному main (новые юзеры подъехали) neonctl branches reset pr-123 --parent main # Удалить ветку после merge PR neonctl branches delete pr-123 # === Vercel + Neon — то же автоматически === # В настройках интеграции: # Preview deployments → Use branch (вместо production DB) # Каждый PR → своя ветка БД → preview URL с настоящими данными # Merge PR → ветка БД удалится автоматически # === Маска чувствительных данных при создании ветки === # Скрипт после neonctl branches create: psql $BRANCH_URL <<SQL UPDATE users SET email = id || '@test.local'; UPDATE users SET phone = NULL; UPDATE payments SET card_last_four = '0000'; SQL
Branching через Neon CLI