破壊的変更のポリシー
許可される変更 (リリース単位)
1 つのリリース内で許可されるのは、既存データを壊さない変更だけです。 具体的には以下のとおりです。
CREATE TABLE— 新しいテーブルの作成ALTER TABLE ... ADD COLUMN— 既存テーブルへのカラム追加 (NULL 許容 or DEFAULT 値ありに限る)CREATE INDEX— インデックス追加INSERT INTO ...— seed データの追加
同一リリース内で禁止される変更
以下の変更は、古いバージョンの Worker が動いている可能性があるため、同一リリースで実行することは禁止されています。 段階的アプローチ (後述) を使ってください。
DROP TABLE— テーブル削除DROP COLUMN— カラム削除ALTER COLUMN TYPE— カラム型変更RENAME TABLE / RENAME COLUMN— 名前変更NOT NULL制約の追加 (DEFAULT なし)UNIQUE制約の追加
破壊的変更を行うときの手順 (3 リリース)
どうしても DROP / RENAME / 型変更が必要な場合は、 以下のように3 リリース挟んで段階的に移行します。 例として「users.email カラムを削除する」ケースで説明します。
リリース N: 新スキーマを additive に追加
- 新しいカラム / テーブルを additive に追加 (旧スキーマはそのまま残す)
- 新コードは新旧両方を読めるようにする
- 書き込みは引き続き旧スキーマ (or 新旧両方)
-- migrations/0042_add_email_address.sql
ALTER TABLE users ADD COLUMN email_address TEXT;リリース N+1: 旧スキーマを deprecate
- 新コードは新スキーマのみに書き込む (旧スキーマには書かない)
- 読み込みは互換性のため引き続き新旧両方
- 既存データのバックフィル migration を実行
-- migrations/0050_backfill_email_address.sql
UPDATE users SET email_address = email WHERE email_address IS NULL;リリース N+2: 旧スキーマを drop
- 新コードは新スキーマのみ参照
- 旧カラム / テーブルを
DROP - この時点で N-1 以前を動かしている Worker は壊れるが、 十分な告知期間を取ったあとなので OK
-- migrations/0058_drop_legacy_email.sql
ALTER TABLE users DROP COLUMN email;なぜ 3 リリース? ユーザーが古いバージョンの Worker をしばらく動かし続ける可能性があるからです。 1 リリースで DROP すると、まだ更新していないユーザーの Worker が DB エラーで動かなくなります。
急ぐ場合: major version bump
段階的な移行が現実的でないほど大規模な変更が必要な場合は、major version をインクリメントして破壊的変更を入れる選択肢があります。
- 例:
v1.x.x→v2.0.0 - リリースノートで明示的に「破壊的変更を含む」と告知
- 移行ガイドを wiki に用意
- ユーザーが手動でアップデート決定 (自動アップデートは major bump で停止)
ただし major bump はユーザー体験を悪化させるので、 できる限り 3 リリース移行を選んでください。
CI で違反 migration を block
scripts/check-migrations.ts という CI スクリプトが、 リリース時に各 migration ファイルを構文チェックします。DROP / RENAME / ALTER COLUMN TYPE などの破壊的キーワードが含まれていると、release.yml ワークフローでリリースが blockされます。
# 違反例 (CI で reject される)
ALTER TABLE users DROP COLUMN email;
ALTER TABLE users RENAME COLUMN name TO display_name;
ALTER TABLE users ALTER COLUMN age TYPE BIGINT;意図的に破壊的変更を入れたい場合は、 コミットメッセージに BREAKING CHANGE: を含めて PR タイトルにも明記してください。レビュー時に手動で承認します。
なぜこのルールが必要か
line-harness は OSS で、ユーザーが各自のサーバーで動かしています。 中央集権的にバージョンを揃えられないので、古いバージョンの Worker が新しい DB スキーマと共存する期間 が必ず発生します。
additive-only ルールにより、新スキーマは古いコードからも安全に 無視できます (古いコードは新カラムを知らないだけで、エラーにならない)。 逆に DROP / RENAME を即時適用すると、未更新の Worker が 「カラムがない」エラーで全停止する事故が起きます。
このポリシーは、line-harness が長期メンテナンスされる OSS であるための 基本契約だと考えてください。