改善・モダナイゼーション

既存サービスを止めずにデータ移行する進め方

2026年07月08日
既存改善 マイグレーション 信頼性 データ移行 無停止

「メンテナンス画面を出せる時間なんて、もうウチにはないんです」——DB移行やクラウド基盤の刷新を相談されるとき、発注者からよく聞く一言です。以前は深夜にメンテナンスを告知して数時間止めれば済んだ移行が、24時間稼働が前提のサービスや海外ユーザーを抱えるサービスでは通用しなくなっています。

一方で「止めずに移行する」を軽く見て、いきなり本番のDBを切り替えて障害を起こす、という事故も後を絶ちません。無停止移行は特別な魔法ではなく、段階を細かく刻み、各段階で戻れる状態を保つという地味な規律の積み重ねです。この記事では、DB移行・スキーマ変更・基盤移行に共通する無停止移行の進め方を整理します。

「止めずに移行する」が必要になる典型パターン

  • DBエンジンやバージョンの移行: MySQL→PostgreSQL、あるいはRDSのメジャーバージョンアップなど、稼働中のデータストア自体を差し替える
  • スキーマの大規模変更: テーブル分割・カラム型変更・正規化のやり直しなど、DB設計そのものの見直しに伴うデータ移行
  • インフラ基盤の移行: オンプレ→クラウド、あるいはクラウド間(AWS間のリージョン移動やアカウント分割含む)でのデータ引っ越し
  • マルチテナント化・シャーディング: 1つのDBに全顧客のデータが同居している状態から、テナントごとに分離する移行

共通するのは「移行中もサービスは書き込みを受け続ける」という制約です。これを無視して一括切替(ビッグバンリリース)をすると、移行時間中のデータが失われるか、切替直後に想定外のエラーが噴出します。

無停止移行の基本設計: Expand-Contractパターン

無停止移行の骨格になるのが Expand-Contract パターンです。3段階で進めます。

  1. Expand(拡張): 新しい構造(新テーブル・新カラム・新DB)を追加する。既存の構造は一切壊さない。この時点ではアプリケーションは旧構造のまま動き続けられる
  2. Migrate(移行): アプリケーションのコードを、新旧両方に書き込み・段階的に新方式から読み取るように変更していく。データそのものもバックフィル(過去データの移し替え)する
  3. Contract(収縮): 新方式が安定稼働したことを確認してから、旧構造を削除する

このパターンの本質は、「構造の変更」と「コードの切り替え」を別々のデプロイに分離することです。1回のデプロイでスキーマ変更とアプリケーションロジックの切り替えを同時にやると、問題が起きたときにどちらが原因か切り分けられず、ロールバックも困難になります。

二重書き込み期間の設計

Expand-Contractの中心にあるのが二重書き込み(dual write)期間です。ここの設計精度が移行全体の成否を分けます。

  • 書き込み経路を1箇所に集約する: アプリケーション内の複数箇所からDBに直接書き込んでいると、二重書き込みの実装漏れが起きる。移行前に書き込みをサービス層やリポジトリ層に集約しておくと安全に進められる
  • 新経路への書き込み失敗を旧経路に波及させない: 新DBへの書き込みでタイムアウトやエラーが出ても、旧DBへの書き込み(=既存ユーザーへの応答)を巻き込んで失敗させない。非同期キューや失敗ログでの後追い再送を使い分ける
  • 書き込み順序と冪等性を意識する: 同じイベントを新旧両方に書く際、リトライで二重に書き込まれても壊れないよう、書き込み処理を冪等(同じ結果になる)に設計する
  • 二重書き込み期間は長すぎても短すぎてもいけない: 短すぎると整合性検証のサンプルが不足する。長すぎると「新旧どちらが正か」の判断が長期化し、開発速度が落ちる。目安は本番トラフィックの1〜2週間サイクル分

整合性検証をどう自動化するか

「新旧のデータが一致している」という確信がないまま読み取りを切り替えるのが、無停止移行で最も多い失敗パターンです。

  • バッチ突合を定期的に回す: 新旧のレコード数・主要カラムの値・集計値(合計金額など)を定期的に突合し、差分をログやSlack通知で可視化する
  • サンプリングでなく全件突合を目指す: データ量が許すなら全件、難しい場合は直近データ+ランダムサンプリングで検証範囲を広げる
  • 読み取り時のシャドー比較(shadow read): 本番トラフィックで実際に新旧両方から読み取り、レスポンスを比較してログに残す(ユーザーへの応答は旧経路のまま)。差分がゼロに近づいてから切り替えると安心感が違う
  • 差分が出たときの許容ライン を事前に決める: 「完全一致でなければ切替不可」なのか「タイムスタンプの数秒ズレは許容」なのか、切替の判断基準を事前合意しておく。現場で都度判断すると基準がぶれる

読み取りの段階切替とロールバック計画

整合性の確信が持てたら、読み取りを新経路に切り替えます。ここも一気にやりません。

  • 影響の小さい機能・ユーザーから切り替える: 管理画面や社内向け機能、あるいはβユーザーやトラフィックの一部(1%→10%→50%→100%)から段階的に切り替える
  • フィーチャーフラグで切替をコード化する: デプロイなしで新旧を切り戻せるよう、切替はフラグやコンフィグで制御する。切り戻しにデプロイが必要な設計は、障害時の対応速度を大きく落とす
  • ロールバック手順は移行開始前に書く: 「うまくいかなかったら旧経路に戻す」を移行途中で考え始めるのは遅い。移行の各段階に対して「この段階で問題が出たら何をするか」を事前に文書化しておく
  • 旧構造は即座に消さない: 読み取り切り替え後も、旧テーブル・旧DBは一定期間(本番トラフィックの1〜2サイクル分)残す。切り戻しの選択肢を早期に失うのが、無停止移行で最も後悔されるミス

リスクが高くなる変更の見分け方

移行作業の中でも、特にロックや長時間処理でサービスを止めかねない操作があります。

  • 大テーブルへのロック系DDL: NOT NULL 制約の追加、カラム型変更、既存カラムへのインデックス追加は、テーブル全体をロックすることがある。PostgreSQLなら NOT VALID 制約や CREATE INDEX CONCURRENTLY でロックを避ける手法を優先する
  • 本番相当のデータ量でのリハーサル必須: 開発環境の数千行なら一瞬のマイグレーションが、本番の数千万行では数十分〜数時間かかることがある。所要時間は事前に本番相当のデータ量で実測する
  • 基盤移行時のネットワーク経路: DBの物理的な移行(オンプレ→クラウドなど)では、移行中の帯域・レイテンシが想定と異なり、想定より長時間かかるケースが多い。事前に転送量とスループットから所要時間を計算しておく

外注する場合に確認すべきこと

無停止移行を外部チームに依頼する際、提案内容から見極められるポイントがあります。

  • Expand-Contract、あるいは同等の段階的移行計画を具体的に提示できるか: 「バックアップを取って一括で切り替えます」という提案は、稼働中サービスには本質的にリスクが高い
  • 整合性検証の方法が具体的か: 「移行後に確認します」ではなく、突合の頻度・範囲・許容差分の基準まで踏み込んで説明できるか
  • ロールバック手順と実施タイミングの基準が明確か: 「問題があれば戻します」ではなく、どの指標がどの閾値を超えたら切り戻すかを事前に定義しているか
  • 段階ごとにデプロイを分離する設計になっているか: スキーマ変更・二重書き込み開始・読み取り切替・旧構造削除が1つのデプロイに詰め込まれていないか

技術的な移行手順そのものより、この「途中で止まれる設計になっているか」という段取りの丁寧さが、無停止移行の成否を分けます。DB設計自体を見直す場合の進め方は既存プロダクトのDB設計を安全に見直す進め方に、着手前の全体的な確認観点は既存プロダクト改善の最初の確認観点にまとめています。私たちが対応するデータベース関連の技術詳細はデータベース関連の技術ページ、進め方全体はモダナイゼーション支援サービスをご覧ください。

まとめ

  • 無停止移行の骨格はExpand-Contractパターン。構造変更・二重書き込み・読み取り切替・旧構造削除を段階ごとに分離し、1回のデプロイに詰め込まない
  • 二重書き込み期間中はバッチ突合やシャドー比較で整合性を機械的に検証し、差分の許容ラインを事前に合意する
  • ロールバック手順は移行開始前に書き、旧構造は読み取り切替後も一定期間残して切り戻しの選択肢を確保する

止められないサービスのデータ移行や基盤刷新を控えていて、進め方に不安がある方は、まず現状の診断からご相談ください。torcheeesでは既存プロダクト改善の診断と、継続的な改善支援を提供しています。お問い合わせフォームから現状を聞かせてください。

プロダクト開発の相談をする

開発相談をする
簡易見積もり