Twelve-Factor App

英語名 Twelve-Factor App
読み方 トゥエルブ ファクター アップ
難易度
所要時間 理解に1〜2日、適用は段階的
提唱者 Heroku(Adam Wiggins)
目次

ひとことで言うと
#

クラウド上で動くSaaSアプリを移植性が高く、スケールしやすく、保守しやすく作るための12の原則。Herokuの共同創業者が、何百ものアプリの運用経験からまとめた方法論。

押さえておきたい用語
#

押さえておきたい用語
ステートレス(Stateless)
アプリケーションのプロセスがリクエスト間で状態を保持しない設計のこと。セッション情報はRedis等の外部ストアに保存する。スケールアウトの前提条件。
環境変数(Environment Variable)
DB接続情報やAPIキーなどの環境固有の設定値を外部から注入する仕組みを指す。コードにハードコードせず、デプロイ先ごとに切り替える。
ポートバインディング(Port Binding)
アプリ自身がHTTPポートをバインドしてサービスを公開する仕組みのこと。外部のWebサーバー(Apache等)に依存しない自己完結型の設計。
バックエンドサービス(Backing Service)
DB、キャッシュ、メールサーバーなど、アプリが利用する外部サービスをアタッチされるリソースとして扱う考え方のこと。接続先をURLで切り替え可能にする。
グレースフルシャットダウン
プロセスが終了シグナルを受けた際に、処理中のリクエストを完了させてから安全に停止する仕組みである。Twelve-FactorのFactor IX(廃棄容易性)に対応。

Twelve-Factor Appの全体像
#

Twelve-Factor App:12の原則をコード・デプロイ・運用の3層で整理
コードと依存関係(Factor I〜III)I. コードベース1リポジトリ複数デプロイII. 依存関係明示的に宣言package.json等III. 設定環境変数で管理コードに埋め込まないビルドと実行(Factor IV〜VII)IV. サービス外部サービスはアタッチリソースV. ビルド分離ビルド→リリース→実行を厳密にVI. ステートレスプロセスは状態を持たないVII. ポート自身でポートをバインドして公開スケールと運用(Factor VIII〜XII)VIII. 並行性プロセスモデルでスケールアウトIX. 廃棄容易高速起動+安全な停止X. 環境一致開発=本番をできる限り一致XI. ログ標準出力にストリーム出力XII. 管理1回限りのプロセスで実行移植性 × スケーラビリティ
Twelve-Factor Appの段階的適用フロー
1
設定の外部化
環境変数で設定を管理、コードに埋め込まない
2
ステートレス化
セッションを外部ストアに移しスケール可能に
3
ビルド・ログ整備
CI/CDパイプライン構築、ログを標準出力に
クラウドネイティブ
docker-compose upで開発、K8sで本番スケール

こんな悩みに効く
#

  • 本番環境と開発環境の差異でデプロイのたびに問題が起きる
  • 環境固有の設定がコードにハードコードされていて移行できない
  • スケールアウトしようとすると、ステートフルな設計が邪魔になる

基本の使い方
#

ステップ1: コードと設定を分離する(Factor I〜III)

コードベース、依存関係、設定を正しく管理する

  • I. コードベース: 1つのリポジトリで複数デプロイを管理する
  • II. 依存関係: すべての依存を明示的に宣言する(package.json、requirements.txtなど)
  • III. 設定: 環境固有の設定は環境変数で管理する。コードにハードコードしない

ポイント: 「git cloneして環境変数を設定すれば動く」状態が理想。

ステップ2: バックエンドサービスとビルドを整理する(Factor IV〜VII)

外部サービスの扱いとデプロイのパイプラインを整備する

  • IV. バックエンドサービス: DB、キャッシュ、メールなどはアタッチされるリソースとして扱う
  • V. ビルド・リリース・実行: ビルド→リリース→実行の3段階を厳密に分離する
  • VI. プロセス: アプリはステートレスなプロセスとして実行する
  • VII. ポートバインディング: アプリ自身がポートをバインドしてHTTPサービスを公開する

ポイント: ステートレスが最重要。セッションはRedisなど外部ストアに保存する。

ステップ3: スケーラビリティと運用を確保する(Factor VIII〜XII)

スケール、環境一致、ログ、管理タスクを整備する

  • VIII. 並行性: プロセスモデルでスケールアウトする
  • IX. 廃棄容易性: 高速な起動とグレースフルシャットダウンを実現する
  • X. 開発/本番一致: 開発・ステージング・本番の環境差を最小にする
  • XI. ログ: ログはイベントストリームとして扱い、標準出力に流す
  • XII. 管理プロセス: マイグレーション等は1回限りのプロセスとして実行する

ポイント: ログをファイルに書かず標準出力に流すのは、コンテナ時代のベストプラクティス。

具体例
#

例1:既存のモノリスアプリをTwelve-Factor化する

状況: 従業員50名のSaaS企業。Rails製のモノリスアプリで、DB接続情報がコードにハードコード、セッションはローカルファイルに保存、ログはアプリ内でファイルに書き込み、デプロイは手動でサーバーにSSH。

Factor III適用: DB接続文字列を環境変数DATABASE_URLに移行。.envファイルで開発環境を管理。

Factor VI適用: セッションをローカルファイルからRedisに移行。これでインスタンスを増やしてもセッションが共有できる。

Factor XI適用: ログ出力先をファイルから標準出力に変更。ログの収集はFluentdやCloudWatch Logsに任せる。

Factor V適用: CI/CDパイプラインを構築し、ビルド→リリース→実行を自動化。

指標BeforeAfter
デプロイ手順SSH+手動(30分)git pushで自動(3分)
スケールアウト不可(セッション問題)水平スケール可能
開発環境構築手順書で半日docker-compose upで5分
本番と開発の差異大きい(障害の原因)ほぼ同一(Docker)

デプロイ30分→3分、環境構築半日→5分。12のうち4つ(III, V, VI, XI)を適用しただけでこの結果。全部一度にやる必要はない。

例2:スタートアップが最初からTwelve-Factorに準拠して構築する

状況: 創業直後の3人チーム。新規SaaSプロダクトをNext.js + Node.js + PostgreSQLで構築。最初からTwelve-Factorに準拠して設計。

設計判断:

  • Factor I: モノレポ(Turborepo)で、フロントとAPIを1リポジトリ管理
  • Factor II: package.jsonpackage-lock.jsonで依存を完全固定
  • Factor III: 全設定を環境変数。Vercel/Railwayの環境変数管理を活用
  • Factor VI: セッションはJWT。サーバーサイドの状態はRedis
  • Factor XI: console.logで標準出力。Datadogで収集

6ヶ月後の状況:

指標結果
新メンバーの環境構築15分(git clone + npm install + .env設定)
デプロイ頻度1日3〜5回
開発→本番の環境差異Docker Composeで完全一致
ユーザー数10倍時のスケール対応設定変更のみ(コード変更ゼロ)

ユーザー数が10倍になった時のスケール対応——コード変更ゼロ、設定変更のみ。3人チームでも最初からTwelve-Factorに準拠しておけば、成長時に「設計のやり直し」は起きない。

例3:地方の中小SIerがレガシーJavaアプリをクラウド移行する

状況: 従業員45名の地方SIer。顧客向けに運用しているJava製業務アプリ(Tomcat + Oracle DB)をAWSに移行したい。現状はオンプレミス1台のサーバーで稼働。DB接続はJNDI設定、ログは/var/log/app/にファイル出力、デプロイはWARファイルを手動配置。

段階的Twelve-Factor化:

PhaseFactor対応内容期間
1IIIDB接続をJNDIから環境変数に移行1週間
2XIログをSLF4J→標準出力に変更、CloudWatch Logsで収集3日
3VIHTTPセッションをElastiCache(Redis)に移行1週間
4VGitHub Actions + ECSでCI/CDパイプライン構築2週間
5IXコンテナ化、グレースフルシャットダウン対応1週間
指標BeforeAfter
デプロイ時間45分(手動)8分(自動)
月間運用コスト120万円(オンプレ保守込み)68万円(AWS)
障害復旧時間平均4時間平均15分
スケール対応不可ECS Auto Scaling

運用コスト120万→68万円、障害復旧4時間→15分。レガシーJavaでもTwelve-Factor化は可能だった。もっとも効果が大きかったのはFactor III(設定の外部化)とFactor VI(ステートレス化)の2つ。

やりがちな失敗パターン
#

  1. 12個全部を一度に適用しようとする — 既存アプリの全面改修は現実的ではない。最もインパクトが大きい項目(III: 設定の外部化、VI: ステートレス化)から段階的に適用する
  2. 設定ファイルを環境変数に移しただけで満足する — 環境変数がカオスになりがち。命名規則を統一し、必要な環境変数の一覧をドキュメント化する
  3. 「ステートレス」を誤解する — アプリにステートがないのではなく、ステートを外部サービスに保存するという意味。一時的な計算結果はメモリに持ってOK
  4. ログをファイルに書き続ける — コンテナ環境ではファイルシステムは揮発性。標準出力に流してログ基盤で収集するアーキテクチャに切り替える

まとめ
#

Twelve-Factor Appは、クラウド時代のアプリケーション設計の基本ルール集。12個すべてを完璧に守る必要はないが、特に設定の外部化、ステートレス化、ログのストリーム化は現代のアプリ開発では必須。既存アプリにも少しずつ適用できるので、できるところから始めよう。