Skip to content

eligibility-verification PG16 本番 実行手順(当日オペ用・自己完結)

🏭 本番当日はこのファイルを上から順に実行する(コピペ可・実識別子入り)。 「なぜ・調査・consumer・設計判断」は preflight.md(リファレンス)。汎用手順の背景は ../../procedure-production.md

フェーズB(CPG 付替+Writer 再起動=瞬断)は 2026-06-30 に実施済み#14065)。 残っているのは フェーズC(BG 作成)→ フェーズD(Switchover)だけメンテ枠は Switchover の1枠のみ

⚠️ 停止を伴うのは §7 の書込断(当日枠・実測 約2秒)のみ。§2 で万一 logical=off だった場合のみ、別枠で reboot(瞬断)が追加になる。 ⚠️ 破壊的操作(reboot・Switchover・旧 blue 削除)は指差し確認。各節の GO 条件を満たしてから進む。 ⚠️ AWS 権限は 参照=production(read-only)/変更・削除=production-admin/terraform=production-terraform。 ⚠️ verify script / terraform は terraform_for_aws リポジトリ(develop) のルートから実行する。


0. 前提・変数(DoR)

  • [ ] preflight 完了(preflight.md・blocker なし)/ consumer は EVS ECS 1系統のみ(cluster endpoint 接続=Secret 変更不要
  • [ ] CPG は作成済みeligibility-verification(PG13 source・付与済)/ eligibility-verification-pg16(PG16 target・cluster/instance 両方)
  • [ ] §2 で rds.logical_replication=on を DB 直で再確認済(2026-06-30 に有効化済み。万一 off なら reboot 枠を別途取る)
  • [ ] メンテ枠・周知(#on本部_release-ops#fdtech-general:3〜5営業日前+前日+当日)/ロールバック判断者 待機
  • [ ] 倫弘 加藤さんに事後の実機 UI 確認(保険証 OCR)を事前に依頼・当日待機を調整(§8-8(b)) ※ EVS Aurora を触るのは OCR だけ。「オン資確認実行」では確認にならない点も併せて伝える
  • [ ] §0-2 の URL を全部タブで開き、各モニターの作業前の状態(Alert / OK)を控える7816201 OCR SLO は移行前から Alert(誤帰属防止)
  • [ ] 監視 mute(対象は 7816263 / 7816201。VPN 系は mute しない=§0-2 参照)
  • [ ] DDL / migration 凍結(BG 同期中は blue へ DDL を流さない)/ アプリリリース凍結
  • [ ] 🔴 ★未適用 migration の解消(BG 作成前・ブロッカー)preflight.md §5-2 本番 _prisma_migrations = 2 だが app repo は 3 本(20260803000000_add_myna_mock_consent_tables・2026-08-04 マージ)。 本番デプロイのたびに prisma migrate deploy が走るため、BG 同期中にデプロイされると CREATE TABLEBlue にだけ流れ、Switchover 後の新 primary に存在せずアプリが落ちる(DDL は Green に複製されない)。 → A(推奨): BG 作成前に本番デプロイを1回通して適用(Green は Blue のコピーなので継承する)/ B: BG 期間中に EVS 本番デプロイが発生しないことを関係者と合意
bash
# 確認: 本番の適用済み migration(BG 作成前と Switchover 後で一致すること)
#   → pgtunnel 後に実行(§0-1)
psql -c "SELECT count(*) FROM _prisma_migrations;"      -c "SELECT migration_name, finished_at FROM _prisma_migrations ORDER BY finished_at;"
bash
# 変数(本番・★ap-northeast-1。us-east-1 ではない)
export AWS_PROFILE=production-admin          # 参照だけなら production(read-only)
R=ap-northeast-1
CL=eligibility-verification
BG_NAME=eligibility-verification-bg
TARGET_VER=16.14                             # staging 実績と揃える(#2678・2026-08-24 に staging 16.14 検証済/13.23→16.14 は ValidUpgradeTarget=major)
BASTION=i-03b8c9b9fb3c4fe9a                  # ★fd-office-connection-bastion(fd-platform 踏み台では DB に届かない)
SECRET=eligibility-verification

# 認証確認(Account=967691968827・変更系の権限があること)
aws sts get-caller-identity --query '{Account:Account,Arn:Arn}' --output json

# 構成を実行直前に再確認(Writer 1台・非-Global・engine 13.23)
aws rds describe-db-clusters --region $R --db-cluster-identifier $CL \
  --query 'DBClusters[0].{Engine:EngineVersion,Status:Status,CPG:DBClusterParameterGroup,Global:GlobalClusterIdentifier,Members:DBClusterMembers[].{id:DBInstanceIdentifier,writer:IsClusterWriter,pg:DBClusterParameterGroupStatus}}' --output json
WRITER=$(aws rds describe-db-clusters --region $R --db-cluster-identifier $CL \
  --query 'DBClusters[0].DBClusterMembers[?IsClusterWriter==`true`].DBInstanceIdentifier | [0]' --output text)
BLUE_EP=$(aws rds describe-db-clusters --region $R --db-cluster-identifier $CL --query 'DBClusters[0].Endpoint' --output text)
echo "WRITER=$WRITER BLUE_EP=$BLUE_EP"

0-2. 📊 当日開いておく画面(URL・作業開始前に全部タブで開く)

Datadog は ap1.datadoghq.com(本組織のサイト)。APM/ログのクエリは env:prdprod ではない)。

CloudWatch(BG の同期・切替を見る)

画面URL
PG16 Blue/Green ダッシュボード(#17738 で作成・green は自動表示)https://ap-northeast-1.console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#dashboards/dashboard/eligibility-verification-aurora-pg16-bluegreen
RDS クラスタ(BG 状態・events)https://ap-northeast-1.console.aws.amazon.com/rds/home?region=ap-northeast-1#database:id=eligibility-verification;is-cluster=true
ECS サービス(タスク・再デプロイ)https://ap-northeast-1.console.aws.amazon.com/ecs/v2/clusters/eligibility-verification-cluster/services/eligibility-verification-service

★ダッシュボードで最優先で見るのは「CPUクレジット」db.t3.medium バースタブル。枯渇すると同期が終わらない・preflight.md §2-1)。

Datadog(アプリ側の異常を見る)

画面URL
APM: eligibility-verification-ms(trace が出ているのはこちら)https://ap1.datadoghq.com/apm/entity/service%3Aeligibility-verification-ms?env=prd
同・エラーhttps://ap1.datadoghq.com/apm/entity/service%3Aeligibility-verification-ms?env=prd#errors
APM: eligibility-verificationhttps://ap1.datadoghq.com/apm/entity/service%3Aeligibility-verification?env=prd
ログ(アプリ本体・ECS)https://ap1.datadoghq.com/logs?query=service%3Aeligibility-verification-ms
ログ(エラーのみ)https://ap1.datadoghq.com/logs?query=service%3Aeligibility-verification-ms ERROR
★★ログ(prisma:query=DB 疎通の直接証拠)https://ap1.datadoghq.com/logs?query=service%3Aeligibility-verification-ms "prisma%3Aquery"
ログ(DB 接続失敗の兆候)https://ap1.datadoghq.com/logs?query=service%3Aeligibility-verification-ms ("Can't reach database server" OR "Connection terminated" OR ECONNREFUSED OR ECONNRESET OR "read-only transaction" OR "does not exist" OR PrismaClientInitializationError OR PrismaClientKnownRequestError)
ログ(オン資 VPN・DB 無関係)https://ap1.datadoghq.com/logs?query=service%3Aeligibility-verification
モニター一覧(EVS 関連)https://ap1.datadoghq.com/monitors/manage?q=eligibility-verification

⚠️ ログのクエリで踏みやすい罠 3 つ(すべて実データで確認・2026-08-20)

  1. service はアプリが eligibility-verification-mseligibility-verification は VPN のログ  service:eligibility-verification で出るのは AWS tunnel ... / received packet: from cgw-... など  オン資 VPN トンネルのログで、アプリのログではない。アプリは必ず -ms を付ける
  2. env タグが付いていないenv:prd を足すと 0 件になる  (APM は env:prd で引けるが、ログには env が無い。ここが非対称)。
  3. status が全部 infostatus:error では 1 件も取れない  ANSI カラー付きの生 stdout がそのまま入っており severity がパースされていない。  ERROR全文検索で拾う(上の「エラーのみ」URL がそれ)。

★★prisma:query ログが DB 疎通の 2 つ目の証拠になる

アプリは Prisma のクエリログを stdout に出しているため、DB へのクエリがログから直接見える(実測・直近1時間):

パターン件数/h意味
prisma:query SELECT 160接続の生存確認(定期的に出る)
prisma:query SELECT ... FROM "public"."prompt_definitions" WHERE "mode" = $187OCR の READ
prisma:query INSERT INTO "public"."ocr_results" (...) RETURNING ...88OCR の WRITE

Switchover 後にこの3パターンが再開すれば、アプリ→Aurora の疎通回復の直接証拠になる。 verify script の 3) pg_stat_activity(DB 側から見た事実)と独立した2系統で確認できるので、 片方が曖昧なときの切り分けに使える。とくに **INSERT INTO ocr_results が出れば「書けている」**ことまで分かる。

★EVS ECS が Aurora に接続される条件=「タスク起動時(eager)+常時接続」

EVS アプリは PrismaPrismaService extends PrismaClient)で、onModuleInit()await this.$connect() を呼ぶ。 =ECS タスクが起動して NestJS が boot した時点で Aurora へ接続が張られる(保険証アップロード等の操作は接続の条件ではない)。以降は Prisma の connection pool が接続を維持(prisma:query SELECT 1 が約1分間隔=60/h で出るのは pool の生存確認)。

  • pg_stat_activity では EVS の ECS 接続が常時 established(idle)で見えるタスクが起動していれば、いつ verify --env production を叩いても捕捉できる(連続 poll 不要)。
  • ⚠️ 対比:online-ops(mental-appointment 側の Kysely reader)は lazy+idle 約10秒で回収のため間欠で、UI 操作中の連続 poll が要る。EVS は Prisma eager+永続 pool なので常時見える、という違いを理解しておく。
  • つまり 接続の“有無”は常時確認できる(起動条件のみ)。アップロードは接続を作るためではなく、read/write の実クエリを流して疎通させたいときに使う。

見るべき Datadog モニター(実機で確認・2026-08-20)

IDモニター意味URL
7816263eligibility-verification-ms-availability 99% AlertMS 全体の可用性/health-check を除外した error rate)https://ap1.datadoghq.com/monitors/7816263
7901944eligibility-verification-insucance-card-availability 99% Alertオン資 /v1/insurance-card の可用性(★Aurora は触らない経路https://ap1.datadoghq.com/monitors/7901944
7816201eligibility-verification-ocr-preview SLO AlertOCR=Aurora を触る唯一の経路の SLOhttps://ap1.datadoghq.com/monitors/7816201
14361699eligibility-verification-vpn-tunnels-both-downオン資 VPN 両系ダウン(DB 無関係)https://ap1.datadoghq.com/monitors/14361699
4993246 / 4993247VPN Tunnel1 / Tunnel2 status片系ダウン(DB 無関係)https://ap1.datadoghq.com/monitors/4993246

通知先はいずれも @slack-fdt-eligibility-verification-error-prod

⚠️ 移行前から Alert 状態のモニターがある(誤帰属を防ぐ)

7816201 OCR preview SLO Alert は 2026-08-20 時点で既に Alert(30日 error budget 超過)。 移行が原因ではないので、当日これが鳴っていても Switchover の影響と誤認しないこと。 逆に言うと OCR の SLO はすでに余裕が無いため、移行で少しでも悪化させると即座に影響が出る。

作業前に各モニターの状態を控えておく(Alert / OK)。移行の影響は「作業前と比べて変わったか」で判断する

監視 mute の対象

§7 の Switchover で数秒の書込断が発生するため、7816263 / 7816201 は mute を検討する (通知が飛ぶと関係者が別事象と混同する)。VPN 系(14361699 / 4993246-49)は DB と無関係なので mute しない ——ここが鳴ったら本当にオン資が止まっているので、mute すると本物の障害を見逃す。


0-1. 踏み台 psql ヘルパ(本手順の psql 系で共通利用・最初に読み込む)

SSM port-forward + Secret 取得を関数化。pgtunnel <db-host> <local-port> 後に psql が使える。終了は pgclose <local-port>。 ⚠️ 踏み台は fd-office 系のみ(EVS の DB SG が fd-platform 踏み台を許可していない・preflight.md §1)。

bash
pgtunnel(){ HOST=$1; LPORT=$2;
  nohup aws ssm start-session --region $R --target $BASTION \
    --document-name AWS-StartPortForwardingSessionToRemoteHost \
    --parameters "{\"host\":[\"$HOST\"],\"portNumber\":[\"5432\"],\"localPortNumber\":[\"$LPORT\"]}" > /tmp/pgt-$LPORT.log 2>&1 &
  for i in $(seq 1 30); do nc -z 127.0.0.1 $LPORT 2>/dev/null && break; sleep 1; done
  nc -z 127.0.0.1 $LPORT 2>/dev/null || { echo "NG: port-forward 未確立(踏み台/SG を確認)"; return 1; }
  SEC=$(aws secretsmanager get-secret-value --region $R --secret-id $SECRET --query SecretString --output text)
  export PGUSER=$(echo "$SEC"     | python3 -c 'import sys,json;print(json.load(sys.stdin)["DB_USERNAME"])')
  export PGPASSWORD=$(echo "$SEC" | python3 -c 'import sys,json;print(json.load(sys.stdin)["DB_PASSWORD"])')
  export PGDATABASE=$(echo "$SEC" | python3 -c 'import sys,json,urllib.parse as u;print(u.urlparse(json.load(sys.stdin)["DATABASE_URL"]).path.lstrip("/"))')
  export PGHOST=127.0.0.1 PGPORT=$LPORT; unset SEC; echo "psql ready: $PGDATABASE @ $HOST (local:$LPORT)"; }
pgclose(){ pkill -f "localPortNumber.*$1" 2>/dev/null; }
# 作業終了時(毎回・必須): unset PGUSER PGPASSWORD PGDATABASE PGHOST PGPORT

⚠️ read-only 確認用と DDL/ANALYZE 用のセッションを分ける。 参照だけなら SET default_transaction_read_only = on; で固定(事故防止)。 CREATE EXTENSION(§3)/ ALTER EXTENSION ... UPDATE(§8)/ ANALYZE(§5⑥)を実行するセッションでは read-only にしないcannot execute ... in a read-only transaction で失敗する)。


1. D-0 保険スナップショット(ロールバック起点)

bash
SNAP=eligibility-verification-pre-pg16-$(date +%Y%m%d%H%M)
aws rds create-db-cluster-snapshot --region $R --db-cluster-identifier $CL --db-cluster-snapshot-identifier $SNAP
aws rds wait db-cluster-snapshot-available --region $R --db-cluster-snapshot-identifier $SNAP
aws rds describe-db-cluster-snapshots --region $R --db-cluster-snapshot-identifier $SNAP \
  --query 'DBClusterSnapshots[0].{id:DBClusterSnapshotIdentifier,engine:EngineVersion,status:Status}' --output json
  • [ ] スナップショット available・engine=13.23$SNAP を控える=ロールバック元)

2. ★フェーズB の効きを再確認(済んでいる前提・数十秒)

フェーズB は 2026-06-30 に完了済み(#14065: 付替前 off/replica/1min → 付替+reboot 後 on/logical/0)。 それでも「その後に誰かが CPG を戻していないか」の確証は DB 直の SHOW でしか取れないため、 BG 作成前に必ず1回実行する(preflight.md §3-2)。

bash
pgtunnel "$BLUE_EP" 5432
psql -c "SET default_transaction_read_only=on;" \
     -c "SHOW rds.logical_replication;" -c "SHOW wal_level;" -c "SHOW wal_sender_timeout;" \
     -c "SHOW shared_preload_libraries;"
結果判断
on / logical / 0想定どおり。そのまま §3 へ(メンテ枠は Switchover の1枠のみ)
off / replica想定外(フェーズB 以降に CPG が戻された)。§2-B の reboot を、Switchover とは別の事前枠で実施し直す

2-B.(万一 off だった場合のみ)Writer 再起動=瞬断

bash
# 付替済みであることを再確認(CPG=eligibility-verification / 値が期待どおり)
aws rds describe-db-cluster-parameters --region $R --db-cluster-parameter-group-name eligibility-verification --source user \
  --query "Parameters[].[ParameterName,ParameterValue,ApplyMethod]" --output table
# 万一まだ default CPG なら付替(無停止・反映は再起動時)
# aws rds modify-db-cluster --region $R --db-cluster-identifier $CL \
#   --db-cluster-parameter-group-name eligibility-verification --apply-immediately

# ★Reader 無し=Writer 1台のみ reboot(瞬断)
aws rds reboot-db-instance --region $R --db-instance-identifier $WRITER
aws rds wait db-instance-available --region $R --db-instance-identifier $WRITER
# in-sync 確認 → §2 の psql をやり直して on/logical/0 を確認
  • [ ] SHOW rds.logical_replication; = onwal_level = logicalwal_sender_timeout = 0

3. BG 作成前: 拡張の確認 + 外部 CDC 最終確認 + ベースライン

pg_stat_statements2026-06-30 のフェーズB で作成済み(#14065)。 Green は同期中 read-only のため CREATE EXTENSION は BG 作成前に blue でやる必要がある(後からでは不可)= ここでは \dx で「既に入っていること」を確認するだけでよい(IF NOT EXISTS なので再実行しても無害)。

bash
pgtunnel "$BLUE_EP" 5432
# ※このセッションは read-only にしない(DDL のため)
psql -c "CREATE EXTENSION IF NOT EXISTS pg_stat_statements;" -c "\dx pg_stat_statements"

# 外部 CDC 最終確認(BG 作成が "external replication" で失敗しないこと。期待: 全て 0 行)
psql -c "SET default_transaction_read_only=on;" \
     -c "SELECT slot_name, plugin, slot_type, active FROM pg_replication_slots;" \
     -c "SELECT pubname, puballtables FROM pg_publication;" \
     -c "SELECT application_name, state FROM pg_stat_replication;"
  • [ ] pg_stat_statements installed(2026-06-30 に作成済=\dx に出るのが正常)/ slot・publication・replication いずれも 0 行(2026-06-30 も 0 行を確認済)
  • [ ] 🔴 _prisma_migrations の件数を記録(BG 作成前の値。Switchover 後に同値であることを §8-1 で確認する) → ここで repo の migration 本数と一致していること(=未適用 migration が無いこと)。不一致なら §0 の A/B を先に解消する
bash
psql -c "SET default_transaction_read_only=on;" -c "SELECT count(*) AS applied FROM _prisma_migrations;"

★性能退行判定用ベースライン(拡張は 2026-06-30 作成=既に十分な統計が蓄積されているはず。当日そのまま取得してよい):

bash
psql -c "\copy (SELECT queryid, query, calls, total_exec_time, mean_exec_time, rows FROM pg_stat_statements WHERE dbid=(SELECT oid FROM pg_database WHERE datname=current_database()) ORDER BY total_exec_time DESC LIMIT 50) TO '/tmp/pg_stat_baseline_evs.csv' CSV HEADER"

PG13 のカラムは total_exec_time/mean_exec_time。§8-6 で post 側と突合する。 ⚠️ CSV の取り扱い注意: query は通常は正規化 SQL だが業務上見せたくない情報を含み得る。保管先・共有範囲を限定し、不要になったら削除する。

★移行前スナップショット(verify script):

bash
bash docs/sre/scripts/pg16-verify-eligibility-verification.sh --env production --label pre
  • [ ] server_version=13.23 / 3テーブルの件数を控えた(参考: 2026-06-30 時点で ocr_results=735,918)/ §4 シーケンス verdict が全て OK

4. BG 作成 → Green 検証

bash
# 4-1 可否ゲート(available / 非-Global / 既存BGなし / target 16.14 が ValidUpgradeTarget にある)
aws rds describe-blue-green-deployments --region $R --query "BlueGreenDeployments[].[BlueGreenDeploymentName,Status]" --output table   # 既存 0 件
aws rds describe-db-engine-versions --region $R --engine aurora-postgresql --engine-version 13.23 \
  --query "DBEngineVersions[0].ValidUpgradeTarget[?EngineVersion=='$TARGET_VER'].EngineVersion" --output text                        # 16.14

# 4-2 BG 作成(★target は cluster PG / instance PG の両方を指定)
SRC_ARN=$(aws rds describe-db-clusters --region $R --db-cluster-identifier $CL --query 'DBClusters[0].DBClusterArn' --output text)
aws rds create-blue-green-deployment --region $R \
  --blue-green-deployment-name $BG_NAME --source "$SRC_ARN" \
  --target-engine-version $TARGET_VER \
  --target-db-cluster-parameter-group-name eligibility-verification-pg16 \
  --target-db-parameter-group-name eligibility-verification-pg16

BG=$(aws rds describe-blue-green-deployments --region $R \
  --query "BlueGreenDeployments[?BlueGreenDeploymentName=='$BG_NAME'].BlueGreenDeploymentIdentifier | [0]" --output text)
echo "BG=$BG"

# 4-3 AVAILABLE 待ち(staging 実測 約31〜33分。Green のみ offline・★Blue は無停止)
watch -n 60 "aws rds describe-blue-green-deployments --region $R --blue-green-deployment-identifier $BG \
  --query 'BlueGreenDeployments[0].{Status:Status,Details:StatusDetails,Tasks:Tasks[].{n:Name,s:Status}}' --output json"

この間ずっと CloudWatch ダッシュボード eligibility-verification-aurora-pg16-bluegreen の 「CPUクレジット」ウィジェットを見るdb.t3.medium はバースタブルで、クレジットを使い切ると ベースライン性能へスロットリングされ 同期が終わらない/レプリラグが 0 に収束しないpreflight.md §2-1)。 残高が 50 を割り込みそうなら、当日枠を諦めて BG を破棄し(§10-A・無停止)、クレジット回復後に再実施する。

4-4 Green 検証(Green の cluster endpoint へ別ポートで port-forward):

bash
GREEN_ARN=$(aws rds describe-blue-green-deployments --region $R --blue-green-deployment-identifier $BG \
  --query "BlueGreenDeployments[0].Target" --output text)
GREEN_EP=$(aws rds describe-db-clusters --region $R --db-cluster-identifier "$GREEN_ARN" --query "DBClusters[0].Endpoint" --output text)
pgtunnel "$GREEN_EP" 15432
PGPORT=15432 psql -c "SET default_transaction_read_only=on;" \
  -c "SHOW server_version;" \
  -c "SHOW shared_preload_libraries;" \
  -c "SELECT (SELECT count(*) FROM ocr_results) ocr, (SELECT count(*) FROM prompt_definitions) prompts, (SELECT count(*) FROM _prisma_migrations) migs;"
  • [ ] server_version=16.14 / shared_preload_librariesrds_blue_green/writeforward を含む(=Green の証拠)/ 件数が blue と一致

ライブ複製確認: アプリ(画面 or GraphQL)で OCR を1件流し、blue の SELECT max(id) FROM ocr_results; の増分が green にも現れることを確認(ラグで一瞬遅れる)。⚠️ 本番では実 PII を伴う操作を新規に起こさない—— 通常トラフィックの自然な増分で確認すれば足りる。


5. ★Switchover 前 GO/NO-GO ゲート(preflight.md §9 準拠)

bash
# ① BG AVAILABLE / StatusDetails=null / SwitchoverDetails 各 AVAILABLE
aws rds describe-blue-green-deployments --region $R --blue-green-deployment-identifier $BG \
  --query "BlueGreenDeployments[0].{Status:Status,Details:StatusDetails,Sw:SwitchoverDetails[].Status}" --output json

# ② green メンバーの CPG in-sync / engine=16.14
aws rds describe-db-clusters --region $R --db-cluster-identifier "$GREEN_ARN" \
  --query 'DBClusters[0].{engine:EngineVersion,members:DBClusterMembers[].{id:DBInstanceIdentifier,pg:DBClusterParameterGroupStatus}}' --output json

# ③ レプリラグ ≒ 0(blue 側 slot)
pgtunnel "$BLUE_EP" 5432
psql -c "SET default_transaction_read_only=on;" \
     -c "SELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS lag FROM pg_replication_slots;"   # 0 bytes

# ④ blue 長時間 tx = 0
psql -c "SET default_transaction_read_only=on;" \
     -c "SELECT pid, state, now()-xact_start AS dur, left(query,60) FROM pg_stat_activity WHERE xact_start IS NOT NULL AND now()-xact_start > interval '1 min' AND pid<>pg_backend_pid();"

# ⑤ blue / green の全テーブル件数が一致(verify script の 2b を両方で取って diff)
bash docs/sre/scripts/pg16-verify-eligibility-verification.sh --env production --label pre   # blue 側(再取得)
#   green 側は 4-4 の psql で件数一致を確認済み

# ⑥ ★green で ANALYZE(read_only を外したセッションで・全テーブル対象)
PGPORT=15432 psql -c "ANALYZE VERBOSE;"

# ⑦ ★CPUCreditBalance に余裕(ダッシュボード or CLI)
aws cloudwatch get-metric-statistics --region $R --namespace AWS/RDS --metric-name CPUCreditBalance \
  --dimensions Name=DBInstanceIdentifier,Value=$WRITER --start-time "$(date -u -v-30M +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --period 300 --statistics Minimum \
  --query 'sort_by(Datapoints,&Timestamp)[-3:].[Timestamp,Minimum]' --output table

# ⑧ 保険スナップショット available(§1)
aws rds describe-db-cluster-snapshots --region $R --db-cluster-snapshot-identifier $SNAP \
  --query 'DBClusterSnapshots[0].{status:Status,engine:EngineVersion}' --output json
  • [ ] ①〜⑧ すべて GO(1つでも欠けたら NO-GO=枠を閉じて延期。BG は §10-A で無停止破棄できる)

6. 直前の最終ゲート再確認(snapshot 待ち等で数分経つため)

bash
aws rds describe-blue-green-deployments --region $R --blue-green-deployment-identifier $BG \
  --query "BlueGreenDeployments[0].{Status:Status,Details:StatusDetails,Sw:SwitchoverDetails[].Status}" --output json
  • [ ] AVAILABLE / Details=null / SwitchoverDetailsAVAILABLE(崩れていたら Switchover しない)

7. Switchover(★書込断 実測 約2秒・当日枠)

bash
aws rds switchover-blue-green-deployment --region $R \
  --blue-green-deployment-identifier $BG --switchover-timeout 300

# 完了ポーリング
aws rds describe-blue-green-deployments --region $R --blue-green-deployment-identifier $BG \
  --query "BlueGreenDeployments[0].Status" --output text     # SWITCHOVER_COMPLETED

# 実体が 16.14・旧は -old1 にリネームされたこと
aws rds describe-db-clusters --region $R --db-cluster-identifier $CL --query 'DBClusters[0].EngineVersion' --output text   # 16.14
aws rds describe-db-clusters --region $R --db-cluster-identifier ${CL}-old1 --query 'DBClusters[0].EngineVersion' --output text  # 13.23
aws rds describe-events --region $R --source-type db-cluster --source-identifier $CL --duration 30 --query "Events[].[Date,Message]" --output table
  • [ ] SWITCHOVER_COMPLETED$CL=16.14 / ${CL}-old1=13.23

8. ⑤ 事後(★アプリ再開の前に 8-1 を必ず通す)

bash
# エンドポイント名は据え置き(identifier 不変)。port-forward を張り直す
pgclose 5432; pgclose 15432
NEW_EP=$(aws rds describe-db-clusters --region $R --db-cluster-identifier $CL --query 'DBClusters[0].Endpoint' --output text)
pgtunnel "$NEW_EP" 5432

★8-1. シーケンス継続性の確認(このサービス最大のリスクpreflight.md §5

bash
# ★post は必ず --wait-ecs を付ける(理由は下の「Switchover 直後は 0 本が正常」)
bash docs/sre/scripts/pg16-verify-eligibility-verification.sh --env production --label post --wait-ecs 180
  • [ ] server_version=16.14
  • [ ] 2c の件数 diff が空(ocr_results の in-flight 数件差は許容)
  • [ ] 🔴 _prisma_migrations の件数が §3 で記録した値と一致(増えていたら BG 中に DDL が流れたpreflight.md §5-2 の事故。テーブル欠落の有無を要確認)
  • [ ] ★4) シーケンス verdict が全て OK/unused(本番の対象は ocr_results_id_seq / prompt_definitions_id_seq の2本)
  • [ ] 3) 接続元→ECS 属性化で接続が復帰している。★本番の期待値=eligibility-verification-service の行が 2 行・各 1 本以上 (ECS desiredCount=2・実測 2026-08-19 / 2026-08-20。1 行しか出なければ片方のタスクが再接続できていない
  • [ ] ★3)backend_startSwitchover 時刻より後になっている(=切替後に張り直された接続=再接続成功の証拠)
  • [ ] 6) in_recovery=false

💡 接続本数の絶対値は合否条件ではない(判定は「1 本以上」)。Prisma はプールを遅延して開き アイドル接続は回収されるため、本数は実行時のトラフィックで変動する。 参考実測(2026-08-20 移行前): 本番は 2 タスク × 各 2 本=計 4 本、staging は 1 タスク 3 本。 見るべきは ①0 本でないか ②2 行そろっているか ③backend_start が切替後か の3点。

⚠️ Switchover 直後は「0 本」が正常 — --wait-ecs を必ず付ける

Switchover は Blue を read-only 化 → エンドポイント DNS を Green に付け替え → Blue を -old1 にリネームする。 つまり切替後に同じホスト名で接続すると **物理的に別のインスタンス(旧 Green)**に繋がる。 旧 Blue への既存接続は切断され(=瞬断)、新 primary の pg_stat_activity はそもそも旧接続を持たない

さらに Prisma は接続を遅延して張る(次のクエリが来るまで再接続しない)ため、

タイミング3) の見え方
pre(Blue)2 行 / 各 2 本 = 計 4 本
post 直後(新 primary)0 行(「少ない」ではなく「無い」)★これは正常
トラフィック到来後2 行 / 各 1〜2 本に回復

--wait-ecs を付けずに post を実行すると、正常なのに ❌ FAIL: 接続が 0 本 と誤検知する。

--wait-ecs 180 の妥当性: 本番の OCR 書込は約 1,460 件/日 ≒ 1 分あたり約 1 件preflight.md §5-1 の実測)。 180 秒あれば期待値で約 3 リクエストが到来し、Prisma が接続を張り直す。

--wait-ecs 180 でも 0 本 / 1 行しか出ない場合は ECS を強制再デプロイする(§12)。 ⚠️ 再デプロイするとタスク IP が変わるが、スクリプトは実行時に aws ecs から IP を再解決するため そのまま再実行してよい(IP を手順書に固定で書いていないのはこのため)。

DRIFT が出た場合の是正(アプリを流す前に実施):

スクリプトは DRIFT したシーケンスの是正 SQL を実際の所有テーブル/列から生成して出力するので、 その出力をそのまま貼って実行すればよい。以下は本番で想定される形(対象は 2 本):

sql
SELECT setval(pg_get_serial_sequence('ocr_results','id'), (SELECT max(id) FROM ocr_results));
SELECT setval(pg_get_serial_sequence('prompt_definitions','id'), (SELECT max(id) FROM prompt_definitions));

是正後にもう一度 verify script を流し、verdict が OK になることを確認する。

8-2〜8-6. 拡張更新・slot・性能

bash
# 8-2 pg_stat_statements を PG16 向けに UPDATE(★read-only にしないセッションで)
psql -c "ALTER EXTENSION pg_stat_statements UPDATE;" -c "\dx pg_stat_statements"    # 1.10

# 8-4 更新が必要な拡張が残っていないか(0 行が正)
psql -c "SELECT name, installed_version, default_version FROM pg_available_extensions WHERE installed_version IS NOT NULL AND installed_version <> default_version;"

# 8-5 BG 用レプリケーション slot が消えていること(0 行が正)
psql -c "SELECT slot_name, slot_type, active FROM pg_replication_slots;"

# 8-6 性能退行チェック: Top SQL を取得し §3 のベースラインと突合
psql -c "\copy (SELECT queryid, query, calls, total_exec_time, mean_exec_time, rows FROM pg_stat_statements WHERE dbid=(SELECT oid FROM pg_database WHERE datname=current_database()) ORDER BY total_exec_time DESC LIMIT 50) TO '/tmp/pg_stat_after_evs.csv' CSV HEADER"
# queryid はアップグレードで変わるため、**クエリ本文・calls・mean/total 時間**で比較する。
# 怪しいものは EXPLAIN (ANALYZE, BUFFERS) でプラン比較。

8-7. 旧 blue(-old1)の残留接続確認(0 行が理想)

bash
OLD_EP=$(aws rds describe-db-clusters --region $R --db-cluster-identifier ${CL}-old1 --query 'DBClusters[0].Endpoint' --output text)
pgtunnel "$OLD_EP" 15433
PGPORT=15433 psql -c "SET default_transaction_read_only=on;" \
  -c "SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE pid<>pg_backend_pid() AND client_addr IS NOT NULL GROUP BY 1,2,3;"
pgclose 15433

8-8. アプリ機能確認

(a) Datadog で観測する(§0-2 で開いたタブ)

見るものURL判断
APM エラー率・レイテンシeligibility-verification-mshttps://ap1.datadoghq.com/apm/entity/service%3Aeligibility-verification-ms?env=prd#errors作業前と比べて悪化していないか
★★ログ: prisma:query の再開https://ap1.datadoghq.com/logs?query=service%3Aeligibility-verification-ms "prisma%3Aquery"SELECT 1 / prompt_definitions SELECT / ocr_results INSERT が再開しているか=疎通回復の直接証拠
ログ: DB 接続失敗の兆候https://ap1.datadoghq.com/logs?query=service%3Aeligibility-verification-ms ("Can't reach database server" OR "Connection terminated" OR ECONNREFUSED OR ECONNRESET OR "read-only transaction" OR "does not exist" OR PrismaClientInitializationError OR PrismaClientKnownRequestError)Switchover 直後の数秒分は許容。継続していたら再接続失敗
ログ: エラー全体https://ap1.datadoghq.com/logs?query=service%3Aeligibility-verification-ms ERROR下の「移行前から出ているエラー」以外の新種が出ていないか
モニター状態https://ap1.datadoghq.com/monitors/manage?q=eligibility-verification§0-2 で控えた作業前の状態と比較
  • [ ] APM のエラー率・レイテンシが作業前と同水準(★7816201 OCR SLO は移行前から Alert。§0-2 の注意参照)
  • [ ] ★★prisma:query の3パターンが再開している(とくに INSERT INTO "public"."ocr_results" =書けている証拠)
  • [ ] DB 接続失敗の兆候が継続していない(Switchover 直後の数秒分のみ)
  • [ ] does not exist(テーブル欠落)が出ていない ← 出たら preflight.md §5-2 の DDL 事故
  • [ ] CloudWatch: DatabaseConnections が回復・CPUクレジット に余裕

⚠️ 移行前から継続的に出ているエラー(誤帰属を防ぐベースライン・2026-08-13〜20 実測)

下記は すべて移行前から出ているもの。当日これを見て「Switchover のせい」と判断しないこと。 判断は「このリストに無い新種が出たか」で行う。

ログ7日間の件数系統
[OnshikakuService] InvalidTokenError: Invalid token specified: missing part #262オン資トークン(DB 無関係)
[OnshikakuService] JWTのDecodeに失敗しました62同上
[OnshikakuClient] {"status":"4007", ... "msg":"RefreshToken is invalid"}41同上
[ExceptionsHandler] Cannot destructure property 'id' of 'this.getCredentials(...)'21オン資(DB 無関係)
[SentryFilter] {"statusCode":500, ... "path":"/v1/insurance-card"}21オン資 500(DB 無関係)
[OcrPreviewResolver] previewInsuranceCardOcr failed / InternalServerErrorException10+10★OCR(7816201 SLO Alert の原因)
[AnalyzeDocumentAzureClientImpl] RestError: Invalid request. / Error: An unexpected error occurred.4+2OCR の文字抽出(Azure)
[AnthropicMastraClientImpl] Error: Type validation failed / Internal Server Error4+3OCR の LLM 整形

DB 起因のエラーは 1 件も出ていないprisma/ECONNREFUSED/Connection terminated 系はゼロ)。 つまり 移行後に DB 系エラーが出たら、それは移行が原因と判断してよい。これが今回いちばん有用な事実。

🔒 ログ調査時の PII 注意

[SentryFilter] のエラーログには medicalInstitutionCode / birthDate / insurerNumber / insuredCardSymbol / insuredIdentificationNumber が平文で入っている(実データで確認)。 ocr_results と同様、調査時は必要最小限の参照にとどめ、スクリーンショット等の共有範囲を限定する。 (ログへの PII 出力自体は本移行の対象外だが、別途改善課題)

(b) ★実機 UI での確認を依頼する(保険証 OCR)

EVS Aurora を触るのは保険証 OCR だけなので、機能面の最終確認は画面から OCR を通すしかない。 ただし 本番では実 PII を伴う新規操作を SRE 側から起こさない方針のため、 業務側の通常オペレーションの中で確認してもらう

  • [ ] 倫弘 加藤さんに実機 UI での確認を依頼(オン資/マイナ資格確認の担当。 Datadog モニター 14158219「同意済資格照会の応答から全員を取り出せていません」の作成者) - 依頼内容: 保険証/医療証の画像アップロード(OCR)が通常どおり完了することImage 保存 → ExecuteOcrJob(非同期)→ EVS POST /v1/ocr/previewocr_results に +1) - ⚠️ 「オン資確認実行」ボタンでは確認にならない — 外部 OQS 照会のみで EVS Aurora に接続すらしない(結果は fastdoctor-manager 自身の DB に入る)。 依頼時にこの点を明示する(preflight.md §6-1) - ⚠️ ExecuteOcrJob非同期なので反映に数十秒〜数分かかる。 また同じ画像の再アップロードは EVS を呼ばない(冪等スキップ)ため、確認は毎回別の新規画像で - 依頼タイミング: §8-1 のシーケンス継続性 PASS 後(DRIFT があると OCR が PK 衝突で落ちるため、 先に是正しておく。壊れた状態で業務側に依頼しない)
  • [ ] SRE 側は DB で増分を確認(実 PII を見ない・id/件数/時刻のみ)
bash
psql -c "SET default_transaction_read_only=on;" \
     -c "SELECT count(*) AS cnt, max(id) AS max_id, max(created_at) AS latest FROM ocr_results;"
  → 加藤さんの OCR 実行後に `max_id` / 件数が増えれば **画面操作 → EVS ECS → Aurora 書込が成立**

💡 通常トラフィックは 約 1,460 件/日 ≒ 1 分あたり約 1 件preflight.md §5-1)あるため、 依頼を待たずとも ocr_results の自然増分で「書けている」ことは確認できる。 加藤さんへの依頼は 業務目線で異常がないこと(画面の見え方・反映速度・エラー表示)の確認が主目的。


9. ⑥ Terraform 整合(★旧 blue 削除より前・preflight.md §12

bash
# 1) コード変更(別PR)を develop にマージ:
#    fastdoctor-template/eligibility-verification/production/main.tf
#      rds_engine_version = "16.14"
#      rds_family         = "aurora-postgresql16"
#      source 側 custom CPG 指定を -pg16 継続利用へ切替(#14418)
# 2) plan で downgrade / replace(ForceNew) が出ないことを確認(★出たら apply しない)
cd fastdoctor-template/eligibility-verification/production
./download-tfvar.sh
AWS_PROFILE=production-terraform terraform plan -var-file=terraform.tfvars -target=module.microservice-ecs
  • [ ] terraform plan に DB の destroy / replace が無い / engine・family が PG16 で no-diff
  • [ ] 凍結解除(terraform apply 再開)はここまで完了してから

10. ⑦ 後片付け

bash
# BG デプロイリソース削除(★--delete-target は付けない=クラスタは残す)
aws rds delete-blue-green-deployment --region $R --blue-green-deployment-identifier $BG

# ── ★旧 blue 削除の直前ゲート(安定確認後・数日後に実施)─────────────────────────
# ⚠️ §8-7 は switchover 直後の点確認。旧 blue 削除は数日後なので、削除の「直前」に再確認する(=本ゲート)。
# ① 誰も旧 blue に接続していないこと
#   (a) CloudWatch: 旧 blue の DatabaseConnections が switchover 以降ずっと 0(日次 Max/Avg)
ST=$(date -u -v-7d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ) ; ET=$(date -u +%Y-%m-%dT%H:%M:%SZ)
aws cloudwatch get-metric-statistics --region $R --namespace AWS/RDS --metric-name DatabaseConnections \
  --dimensions Name=DBClusterIdentifier,Value=${CL}-old1 --start-time "$ST" --end-time "$ET" \
  --period 86400 --statistics Maximum Average --query 'sort_by(Datapoints,&Timestamp)[].{day:Timestamp,max:Maximum,avg:Average}' --output table
#   → 全日 max=0 / avg=0 が GO 条件(1つでも >0 なら消費者が残っている=削除しない・接続元を特定して repoint)
#   (b) 直前の pg_stat_activity 残留 0(§8-7 と同じ手順を旧 blue endpoint に対して再実行)
# ② ロールバック保険(§1 D-0 手動スナップショット)が available で残っていること=削除後の唯一のフォールバック
aws rds describe-db-cluster-snapshots --region $R --snapshot-type manual \
  --query "DBClusterSnapshots[?contains(DBClusterSnapshotIdentifier,'pre-pg16')].{id:DBClusterSnapshotIdentifier,engine:EngineVersion,status:Status}" --output table
# ────────────────────────────────────────────────────────────────────────────

# 上記ゲート GO 後に旧 blue を削除。★Writer 1台のみ → instance → cluster の順
# ★member 名は実測で ${CL}-0-old1(${CL}-old1-0 ではない)。ハードコードせず動的取得する。
OLD_MEMBER=$(aws rds describe-db-clusters --region $R --db-cluster-identifier ${CL}-old1 --query 'DBClusters[0].DBClusterMembers[].DBInstanceIdentifier' --output text)
aws rds delete-db-instance --region $R --db-instance-identifier "$OLD_MEMBER" --skip-final-snapshot
aws rds wait db-instance-deleted --region $R --db-instance-identifier "$OLD_MEMBER"
# ★cluster は deletion protection が有効なことがある(有効だと delete が InvalidParameterCombination で失敗)→ 先に無効化
aws rds modify-db-cluster --region $R --db-cluster-identifier ${CL}-old1 --no-deletion-protection --apply-immediately
aws rds delete-db-cluster --region $R --db-cluster-identifier ${CL}-old1 --skip-final-snapshot

# CloudWatch ダッシュボードの撤去(コスト最適化・様子見後)
#   fastdoctor-template/eligibility-verification/production/pg16_dashboard.tf の module ブロックを削除して apply

11. ロールバック

A) Switchover 前(BG 作成〜ゲートまで)=無停止で安全

bash
# BG を破棄すれば blue(13.23) が無傷で継続(★--delete-target は付けない)
aws rds delete-blue-green-deployment --region $R --blue-green-deployment-identifier $BG
  • §2-B で reboot していた場合も、logical=1 は BG 以外に実害がないため戻す必要はない(値の見直しは #13044)。

B) Switchover 後・旧 blue(eligibility-verification-old1)未削除 = ★post-switchover の書込は喪失

bash
# 1) old1(13.23) の存在・エンドポイント確認
OLD1_EP=$(aws rds describe-db-clusters --region $R --db-cluster-identifier ${CL}-old1 --query 'DBClusters[0].Endpoint' --output text)

# 2) consumer を old1 エンドポイントへ向け直す
#    ★rename しても endpoint hash が変わり元 DNS には戻らない=**Secret の DATABASE_URL 更新が必要**
#    DATABASE_URL(secret) の host を $OLD1_EP に置換した JSON を put:
# aws secretsmanager put-secret-value --region $R --secret-id $SECRET --secret-string '<host を置換した JSON>'
#    ⚠️ Secret 値は Terraform 管理(jsonencode)のため、次の apply で上書きされる。恒久化するなら TF 側も直す。
#    → ECS を強制再デプロイして再接続
aws ecs update-service --region $R --cluster eligibility-verification-cluster \
  --service eligibility-verification-service --force-new-deployment

# 3) 13.23(old1) に戻ったこと・アプリ疎通を確認
bash docs/sre/scripts/pg16-verify-eligibility-verification.sh --env production --label post

C) Switchover 後・old1 も削除済 = §1 のスナップショットから復元

bash
aws rds restore-db-cluster-from-snapshot --region $R \
  --db-cluster-identifier ${CL}-restore --snapshot-identifier $SNAP --engine aurora-postgresql
# → instance を作成し、consumer を restore クラスタ endpoint へ向け直す(B-2 と同手順で Secret 更新+再デプロイ)

12. 接続残留時の復旧手順(§2-B reboot / §7 Switchover 共通)

Switchover / reboot 後に ECS が古い接続を掴んだままエラーを出す場合:

bash
# ECS を強制再デプロイして接続を張り直す(Fargate・desired 2)
aws ecs update-service --region $R --cluster eligibility-verification-cluster \
  --service eligibility-verification-service --force-new-deployment
aws ecs wait services-stable --region $R --cluster eligibility-verification-cluster \
  --services eligibility-verification-service

# 復帰確認(接続元→ECS 属性化で新タスクの接続が現れること)
bash docs/sre/scripts/pg16-verify-eligibility-verification.sh --env production --label post

13. タイムスケジュール

フェーズB は 2026-06-30 に完了済み(#14065)=瞬断を伴う事前枠は不要。この1枠で完了する。 万一 §2 で off が出たら別枠で §2-B(Writer reboot=瞬断)を先に消化する。

13-0. 事前作業(当日枠の外・前日までに完了させる)

いつ作業参照
3〜5営業日前メンテ枠の周知(#on本部_release-ops#fdtech-general)/ロールバック判断者の確保§0
3〜5営業日前倫弘 加藤さんへ事後の実機 UI 確認(保険証 OCR)を依頼・当日待機を調整§8-8(b)
🔴 前日まで★未適用 migration の解消(本番デプロイを1回通す or BG 期間中のデプロイ停止合意)preflight.md §5-2
前日までDDL / migration 凍結・アプリリリース凍結の合意と周知§0
当日直前§0-2 の URL を全部開き、各モニターの状態(Alert / OK)を控える§0-2

pg_stat_statements2026-06-30 に作成済み(#14065)なので統計は十分蓄積されている。 旧手順書が「ベースライン取得を 4 時間前に置く」としていたのは拡張作成直後を想定した記述で、現在は不要

13-1. 準備フェーズ(約2時間・★Blue 無停止=サービス停止ではない)

経過作業備考
T-2:00§2 logical 確認(on/logical/0数十秒。off なら中止して §2-B の枠を取り直す
T-1:55§3 拡張確認・外部CDC 確認・_prisma_migrations 件数の記録・Top SQL ベースライン CSVread-only
T-1:45§3 verify script --label pre3テーブル件数・シーケンス・ECS 接続 2 行を記録
T-1:35§4-1 可否ゲート → §4-2 BG 作成
T-1:35〜T-0:55AVAILABLE 待ち(staging 実測 約31〜33分)CPUクレジットを監視⚠️ 下の「延びたら」参照
T-0:55§4-4 Green 検証(server_version=16.14 / 件数一致 / shared_preload_librariesrds_blue_green
T-0:45§5⑥ green で ANALYZE VERBOSE(切替後の性能事故防止)3テーブルなので僅少
T-0:35DDL / migration 凍結の最終確認(同期中は Blue へ DDL を流さない)🔴 _prisma_migrations が T-1:55 の値と同じか再確認
T-0:25§1 保険スナップショット取得 → available 待ち数分。ロールバック起点($SNAP を控える)
T-0:10§5 GO/NO-GO ゲート(①〜⑧)1つでも欠けたら NO-GO
T-0:05§6 最終ゲート再確認 → GO/NO-GO 判断/加藤さんに「これから切替」を連絡NG なら枠を開かず延期(§11-A で無停止破棄)

⚠️ BG 作成が想定より延びたときの判断

db.t3.medium はバースタブルで、CPU クレジットが枯渇するとベースライン性能へスロットリングされ 同期が終わらないpreflight.md §2-1)。

  • T-0:55 を過ぎても AVAILABLE にならない → CPUクレジット残高を確認
  • 残高が枯渇方向 → 当日枠を諦め、§11-A で BG を破棄(Blue 無傷・無停止)してクレジット回復後に再実施
  • この判断を T-0:35(DDL 凍結最終確認)までに行う。snapshot を取ってから諦めるのは時間の無駄

13-2. 正式メンテ枠(T0〜T+1:00・サービス停止扱い・周知済み)

経過作業備考
T0§7 Switchover 実行(★書込断 実測 約2秒)
T+0:02§7 完了・リネーム確認(SWITCHOVER_COMPLETED / -old1
T+0:05🔴 §8-1 シーケンス継続性の確認(★アプリ再開前・最重要)DRIFT なら setval で是正してから先へ
T+0:05§8-1 _prisma_migrations が §3 の値と一致(増えていたら DDL 事故)preflight.md §5-2
T+0:10§8-2〜8-5 拡張更新(ALTER EXTENSION ... UPDATE)/ slot 0 確認
T+0:15§8-8(a) Datadog / CloudWatch 観測★★prisma:query の3パターン再開=疎通回復の直接証拠
T+0:15§8-8(b) 加藤さんへ実機 UI(保険証 OCR)確認を依頼★§8-1 PASS 後に依頼する
T+0:20§8-6 Top SQL を取得し T-1:55 のベースラインと突合性能退行チェック
T+0:25§8-7 旧 blue(-old1)の残留接続 0 を確認
T+0:20〜T+1:00★監視バッファ(40分): エラー率・レイテンシ・DB接続・ocr_results 増分を監視。ロールバック判断者が待機異常時は §11 で判断(復元元 $SNAP

13-3. 枠の考え方(周知文面に使う)

  • 実際の書込断は Switchover の数秒(staging 実測 約2秒)。それでも再接続・DNS 伝播・事後確認・ ロールバック余地を含め 1時間を「サービス停止」枠として周知する(安全マージン)。
  • 準備フェーズ 2 時間は Blue が稼働し続ける=サービス停止ではない。 中身は BG 作成(約33分)+ Green 検証 + snapshot + ゲートで、利用者影響はない。 周知時にここを混同されると「2時間止まる」と誤解されるので、停止は T0 以降の枠だけと明記して伝える。
  • GO/NO-GO は T-0:05 で判断し、NG なら枠を開かない。BG は §11-A で無停止のまま破棄できるので、 無理に進めるより延期の方が安い。

13-4. 枠を跨がない場合の後片付け(数日後)

いつ作業参照
Switchover 当日〜翌営業日§9 Terraform 整合(★旧 blue 削除より前・plan に destroy/replace が無いこと)§9
安定確認後(数日)§10 BG レコード削除 → 旧 blue(-old1)削除 → source 側 PG13 CPG 削除§10
様子見後CloudWatch ダッシュボードの撤去(module ブロック削除して apply)§10