Neonによるデータベースブランチ機能:本番環境でのマイグレーション失敗の恐怖から解放される

Database tutorial - IT technology blog
Database tutorial - IT technology blog

深夜のマイグレーションという悪夢

migration failed: relation "users" already exists というエラーメッセージが赤々と表示される。時は午前2時。従来のPostgreSQLサーバーで、デプロイに失敗した環境のロールバックに四苦八苦している最中だ。スキーマが新旧の状態の間で立ち往生している間にも、新しいデータは次々と流れ込んでくる。選択肢は2つ。パニックになりながら手動でクエリを修正するか、昨晩のバックアップをリストアするために数時間分のデータを失うことを受け入れるかだ。

MySQL、MongoDB、Postgresを長年扱ってきた中で、Postgresはデータ整合性の面で常にトップだと感じている。しかし、そのステージング環境の管理は苦行だ。500GBのデータベースを複製し、わずか10分のマイグレーションスクリプトを実行するためだけに準備することは、通常のRDSシステムではほぼ不可能に近い。

Neonの登場はこの状況を完全に変えた。自動スケーリングが可能なServerless PostgreSQLであるだけでなく、Neonは究極の武器「Database Branching」を備えている。Copy-on-Write技術により、テラバイト級の本番データベースのコピーをわずか2秒足らずで作成できるのだ。あなたのCI/CDワークフローは、今日から新しいステージへと進むだろう。

Neonプロジェクトの設定:ゼロから接続文字列まで

面倒なDockerやサーバー設定のことは忘れよう。Neonはストレージ層とコンピューティング層を完全に分離しているため、セットアップが驚くほど速い。

まずは neon.tech にアクセスしてアカウントを作成する。プロジェクトを作成すると、次のような構造の接続文字列(Connection String)が発行される。

postgres://alex:[email protected]/neondb?sslmode=require

個人的に非常に気に入っているのが Autoscale 機能だ。最小値を0.25 CU(Compute Unit)に設定できる。トラフィックがない時はデータベースが自動的に「スリープ」状態(Scale to zero)になる。これにより、開発環境やユーザーの少ないサイドプロジェクトでは、コストを最大90%削減できる。

Neon CLIをプロのように使いこなす

Webインターフェースでの操作も便利だが、生産性を最大限に高めるならCLIを使うのがエンジニアの流儀だ。以下のツールをインストールしよう。

npm install -g neonctl
neonctl auth

ブラウザ経由での認証が終われば、ターミナルからデータベースインフラ全体を操作できる準備が整う。

Database Branching:データのための真のGit

通常、新機能をテストするには本番データをローカルにダンプする必要がある。この方法は時間がかかるだけでなく、機密データ漏洩のリスクも孕んでいる。Neonなら、各データベースブランチが独立した環境として機能する。

例えば、main ブランチにいて、orders テーブルにカラムを追加するスクリプトをテストしたいとする。直接操作してはいけない。専用のブランチを作成しよう。

# 'main'ブランチから'feature-add-column'ブランチを作成
neonctl branches create --name feature-add-column --parent-id main

# 即座に接続するための接続文字列を取得
neonctl connection-string feature-add-column

このブランチ上での ALTER TABLE やデータの削除といった変更は、元のデータには一切影響しない。もし失敗しても、削除して最新の本番データから新しいブランチを作り直すのに、わずか2秒しかかからない。

GitHub Actionsに統合して完全自動化する

私はよくNeonをCI/CDワークフローに組み込んで、プレビュー環境を構築している。プルリクエスト(PR)が作成されるたびに、システムが自動的に専用のデータベースブランチを作成する。統合テスト(Integration Test)はこの実データ上で直接実行される。

以下は、このプロセスを自動化するためのワークフローのサンプルだ。

name: Preview Environment DB
on: [pull_request]

jobs:
  setup-db:
    runs-on: ubuntu-latest
    steps:
      - name: Create Neon Branch
        id: create-branch
        run: |
          # PR用の新しいブランチを作成するためにNeon APIを呼び出す
          BRANCH_DATA=$(curl -X POST "https://console.neon.tech/api/v2/projects/${{ secrets.NEON_PROJECT_ID }}/branches" \
            -H "Authorization: Bearer ${{ secrets.NEON_API_KEY }}" \
            -H "Content-Type: application/json" \
            -d '{"branch": {"name": "pr-${{ github.event.number }}"}}')
          
          DB_URL=$(echo $BRANCH_DATA | jq -r '.connection_uris[0].connection_uri')
          echo "DATABASE_URL=$DB_URL" >> $GITHUB_ENV

      - name: Run Migrations and Tests
        run: |
          npm install
          npx prisma migrate deploy
          npm test

PRがマージされると、別のジョブがこのブランチを削除してリソースを最適化する。この手法により、各開発者が独立した安全な遊び場を持つことができる。

実戦経験:よくある「落とし穴」を避けるために

Neonは非常に柔軟だが、システムを円滑に運用するために以下の3点に注意してほしい。

  • コールドスタートへの対応: サーバーレスモードでは、クエリがないとデータベースが一時停止する。初回アクセス時に500msから2秒程度の遅延が発生する可能性がある。即時のレスポンスが必要なアプリでは、min_cu を0より大きく設定し、常にデータベースを「温めて」おく必要がある。
  • コネクションプーリングの活用: NeonにはPgBouncerが標準で統合されている。常にポート 5432 または末尾に -pooler が付いたエンドポイントを使用すること。これにより、トラフィックが急増した際に応プリケーションが「too many connections」エラーで停止するのを防げる。
  • 定期的なクリーンアップ: ブランチ作成は容量ベースでは無料だが、プランによって作成できる数に制限がある。作業が終わったらテスト用ブランチを削除する習慣をつけよう。

ダッシュボードで指標を確認することも欠かせない。CPUが頻繁に100%に達する場合は、Max CU の上限を引き上げるか、EXPLAIN ANALYZE を使って遅いクエリを最適化しよう。データベースをコードのように柔軟に作成・削除できるリソースとして捉えることで、プロジェクトの開発スピードは劇的に向上するはずだ。

Share: