2026 年 5 月 28 日、Zenn Trending で 論理削除をやめて状態をテーブルで分ける DB 設計 がランキング上位に入り、業務 SaaS 開発者の間で広く議論されています。記事は deleted_flag / is_deleted / deleted_at という 汎用論理削除パターンが、**「削除」と「アーカイブ」と「無効化」と「失効」と「退会」を 1 つのフラグで表現することで、業務 SaaS の不整合 / クエリ複雑化 / インデックス肥大化 / 監査ログ不能を引き起こす構造を整理。「状態を別テーブルに切り出す」+「イベントログを持つ」設計への 段階移行を提案しています。同時期、gihyo.jp では Bintrail で MySQL に「タイムトラベルクエリ」を ─ DB フォレンジック受託を設計する 2026 も参照されており、「データの履歴を正しく持つ」**が 2026 年の DB 設計の主流になりつつあります。
受託で中堅企業の 業務 SaaS / 基幹システム / 管理画面を支える立場では、これは 「論理削除で運用されてきた既存 DB」を **「状態テーブル + イベントログ」に 段階的に再設計する受託機会を意味します。これまで Cloudflare Dynamic Workflows 受託 で扱った マルチテナント SaaS 耐障害、Bintrail MySQL タイムトラベル受託(GH Media) で扱った DB フォレンジック、Monzo データメッシュ受託 で扱った データ統治と接続して、「論理削除を捨てる DB 再設計」**を 受託パッケージとして整理します。
なぜ「論理削除廃止が分水嶺」なのか
| 観点 | 論理削除(deleted_flag 型) | 状態テーブル + イベントログ |
|---|---|---|
| 表現できる状態 | 2 値(生存 / 削除) | 任意(active / archived / suspended / withdrawn …) |
| クエリの複雑度 | 全クエリで WHERE deleted_at IS NULL | 状態テーブル JOIN |
| インデックス効率 | フラグ列で肥大化 | 状態別に最適化可能 |
| 監査ログ | 「いつ」「誰が」が不明確 | イベントログで完全保持 |
| GDPR / 退会対応 | 物理削除と齟齬 | 状態別に削除ポリシー定義 |
| 業務ルール | アプリ側に散在 | 状態遷移テーブルで一元化 |
| データ復旧 | フラグを戻すだけ | イベント巻き戻し |
| テスト | 各クエリの境界条件爆発 | 状態 × イベントで網羅 |
| 業務理解 | コード読まないと分からない | スキーマで自己説明的 |
つまり「論理削除廃止」は DB の小手先のリファクタリングではなく、「データに業務状態を語らせる」という 業務ドメインの再表現です。
受託案件で活きる 3 つの構造変化
構造 1: 「削除フラグの増殖」から「状態テーブル正規化」へ
中堅企業の業務 SaaS は is_deleted / is_archived / is_suspended / withdrawn_at / expired_at…と フラグが増殖し、クエリが破綻しているケースが多数あります。受託では 業務状態の棚卸し → 状態遷移図 → 状態テーブル設計を 2〜3 ヶ月で実施します。これは Monzo データメッシュ受託 で扱った データ統治の OLTP 側設計版です。
構造 2: 「いつ消されたか不明」から「イベントログ完全保持」へ
論理削除では 「誰が / いつ / なぜ」消したかが アプリログ頼みになりがちで、監査 / 規制 / インシデント調査で苦しみます。受託では イベントソーシング軽量版(状態変更だけイベントログ保持)を導入し、監査 + 復旧 + 分析を一気に解決します。これは Bintrail MySQL タイムトラベル受託 で扱った DB フォレンジックの アプリ層設計版です。
構造 3: 「アプリ側に散在した業務ルール」から「状態遷移テーブル」へ
「退会済みは更新不可」「アーカイブ済みは検索除外」等の 業務ルールがアプリ各所に散在すると、仕様変更が地獄になります。受託では 状態遷移テーブル + ガード関数で 業務ルールを DB / バックエンドに集約し、フロント / バッチを薄くします。これは Cloudflare Dynamic Workflows 受託 で扱った 耐障害ワークフローの データモデル統治版です。
受託で提供する「論理削除をやめる DB 再設計」5 フェーズ
フェーズ 1: 現状診断(2〜3 週間)
- 主要テーブルのフラグ / 状態列棚卸し
- 業務状態の整理(active / archived / suspended / withdrawn / expired …)
- クエリパターン棚卸し(
WHERE条件 / インデックス利用) - 監査要件 / 規制要件確認
- パフォーマンス計測(スロークエリ / インデックス効率)
- 影響範囲マップ(アプリ / バッチ / 分析 / BI)
フェーズ 2: 設計(2〜4 週間)
- 業務状態モデルの確定(状態遷移図)
- 状態テーブル設計(正規化 / インデックス)
- イベントログ設計(不変 / 追記専用 / TTL)
- アプリ側ガード関数 / リポジトリ層
- 段階移行計画(Strangler Pattern)
- 監査クエリテンプレ
フェーズ 3: PoC + 1 ドメイン適用(4〜6 週間)
- 主要 1 ドメイン(例: ユーザー / 注文 / 契約)でフル実装
- 並走稼働(旧フラグ + 新状態テーブル + イベントログ)
- 整合性検証 + 性能比較
- 既存クエリの書き換え
- BI / 分析クエリの追従
フェーズ 4: 全面展開(3〜6 ヶ月)
- ドメイン別の順次移行
- 旧フラグの段階廃止
- アプリ / バッチの書き換え
- 監査ダッシュボード整備
- ステークホルダー教育
フェーズ 5: 月次運用(継続)
- 状態遷移 KPI モニタリング
- イベントログ容量管理 / TTL 運用
- 新規業務要件への状態追加対応
- パフォーマンス改善
- 半期ごとの設計見直し
受託向け技術スタック標準セット
| レイヤ | 推奨技術 | 代替 |
|---|---|---|
| DB | PostgreSQL / MySQL 8 / Aurora | TiDB / CockroachDB |
| イベントログ | テーブル追記 / Outbox + Kafka | EventStoreDB |
| マイグレーション | Atlas / sqldef / 自社内製 | Flyway / Liquibase |
| ORM / クエリ | Drizzle / sqlc / Prisma | TypeORM |
| 状態遷移 | XState / 自社内製 DSL | finite-state-machine |
| 監査クエリ | dbt / SQL / メトリクスストア | Looker / Metabase |
| 観測 | Datadog / Honeycomb | Sentry Performance |
| データ品質 | Great Expectations / dbt tests | Soda |
どの SaaS に必要か / 不要か
| 必要な SaaS | 不要な SaaS |
|---|---|
| 業務状態が複雑(3 値以上) | 単純な CRUD |
| 監査 / 規制 / コンプラ対応必須 | 内部利用のみ |
| 業務ルールがアプリ各所に散在 | ルール少数で安定 |
| 退会 / 失効 / 一時停止が業務に存在 | 状態は生存 / 削除のみ |
| データ復旧 / 履歴照会の要望あり | 履歴不要 |
受託契約に書く 7 つの条項
| 条項 | 内容 | 顧客が確認すべきこと |
|---|---|---|
| 対象ドメイン | 移行対象テーブル / 機能 | 除外対象 |
| 業務ルール表 | 状態遷移 / ガード条件 | 業務部門承認 |
| データ整合性 | 旧フラグ / 新状態の検証手順 | 不整合時の対応 |
| 監査ログ要件 | 保管期間 / 検索 / 法令 | 規制対応 |
| パフォーマンス SLA | クエリ応答時間 / スループット | KPI 連動 |
| 段階移行 | Strangler / フィーチャーフラグ | ロールバック手順 |
| 退場時引き渡し | スキーマ / 業務ルール表 / 運用手順 | 自社運用継続性 |
価格モデル — 論理削除廃止 DB 再設計パッケージ
| プラン | 金額 | 対象 | 内容 |
|---|---|---|---|
| 診断 / 設計 | 80 万円〜(4 週間) | 業務状態棚卸し + 設計書 | レポート + 設計書 |
| 小規模ドメイン移行 | 250 万円〜(2〜3 ヶ月) | 1 ドメイン / 数テーブル | 状態テーブル + イベントログ |
| 中規模 SaaS | 500 万円〜(4〜6 ヶ月) | 主要 3〜5 ドメイン | 全面 + 監査ダッシュボード |
| 大規模 / 基幹系 | 1,000 万円〜(6〜12 ヶ月) | 10 ドメイン以上 | 段階移行 + BI 連携 + 教育 |
| 月次運用 | 30〜80 万円 / 月 | 新規状態追加 + 性能改善 | KPI + 設計レビュー |
顧客側 ROI 試算(中規模 SaaS / 100 テーブル想定)
| 項目 | 論理削除運用 | 状態テーブル + イベントログ | 差分 |
|---|---|---|---|
| スロークエリ件数 | 月 80 件 | 月 20 件 | -60 件 |
| データ不整合インシデント | 月 5 件 | 月 0.5 件 | -4.5 件 |
| 監査 / 規制対応工数 | 80 時間 / 月 | 15 時間 / 月 | -65 時間 |
| 仕様変更の影響範囲調査 | 40 時間 / 件 | 8 時間 / 件 | -32 時間 |
| データ復旧対応時間 | 4 時間 / 件 | 0.5 時間 / 件 | -3.5 時間 |
| 年間効果 | — | — | 約 1,200 万円相当 + インシデント -90% |
時給 8,000 円換算で 年間 1,000 万円超の工数削減 + インシデント / 監査リスク低減の事業効果。中規模 SaaS パッケージ(500 万円〜)でも 8 ヶ月以内で回収可能です。
ハマりやすい 5 つの落とし穴
落とし穴 1: 「フラグを増やすだけ」のリファクタ
status 列を追加して deleted_flag と併用するだけでは 両方を WHERE に書く時代が始まります。状態テーブルへの正規化 + 旧フラグの段階廃止を 設計時に確定します。
落とし穴 2: 「全テーブル一斉移行」
100 テーブルを一気に変えると 不整合検知が破綻します。Strangler Pattern + ドメイン単位 + 並走稼働で 2〜3 ヶ月単位で進めます。
落とし穴 3: イベントログの「とりあえず全部保存」
全行更新をイベント化すると 容量が爆発します。状態変更だけログに保持し、TTL + アーカイブを 設計時に決定します。
落とし穴 4: BI / 分析クエリの書き換え漏れ
OLTP 側を変えても dbt / BI / 経営ダッシュボードを書き換えないと 数値の不整合が経営層に届きます。移行スコープに BI を必ず含めること。
落とし穴 5: 業務部門への合意なし
「業務状態の定義」は エンジニアだけで決められない領域です。業務部門ワークショップ → 状態遷移図合意を 必ず先に実施します。
90 日アクションプラン
| 週 | アクション |
|---|---|
| Week 1〜2 | 現状診断 + フラグ列棚卸し + パフォーマンス計測 |
| Week 3〜4 | 業務部門ワークショップ + 状態遷移図合意 |
| Week 5〜6 | 状態テーブル + イベントログ設計書 |
| Week 7〜9 | 1 ドメイン PoC + 並走稼働 |
| Week 10 | 整合性検証 + 性能比較 |
| Week 11 | BI / 分析クエリ書き換え |
| Week 12 | 主要 1 ドメイン本番切り替え |
| Week 13 | 月次運用契約 + 残ドメインの展開計画 |
まとめ — 「データが業務を語る」DB 設計へ
deleted_flag 1 つで 5 つの業務状態を表現してきた時代は、業務 SaaS の複雑化 + 監査要件 + データ復旧要求の前で 限界に達しています。受託で中堅企業の 業務 SaaS / 基幹系を支える立場では、診断 + 設計 + PoC + 段階展開 + 月次運用を一体で提供する 「論理削除廃止 DB 再設計」が新しい主力サービスになります。
弊社では 診断 / 小規模 / 中規模 / 大規模 / 月次運用 の 5 種類で本パッケージを提供しています。「deleted_flag で全クエリが破綻している」「監査ログが取れない」「退会 / 失効 / 停止の仕様が分かれている」というご相談は お問い合わせフォーム からお気軽にどうぞ。