プロダクションアプリ
アイデア
大企業は皆、同じ形状に収束します。前面にエッジ、デプロイ可能なフロントエンド、ゲートウェイの背後にある独立したバックエンド、キューからジョブを消費するワーカー、単一のリレーショナル記録システム、キャッシュ、イベントまたはジョブのバックボーン、オブジェクトストレージ、そしてそれら全体を監視するオブザーバビリティです。Shopify、Notion、Figma、Instacart、Airbnbは言語やベンダーが異なるだけで、形状は変わりません。
この形状は、週末のMVPとプラットフォームチームを持つ企業の間でも変わりません。変わるのは、各ボックスの背後にあるプロバイダーだけです。そこで、このスキルは初日から完全な形状を安価なマネージドプロバイダーで構築し、少数の移植性ルールを適用し、測定可能なトリガーが発火したときにプロバイダーを交換するためのプレイブックをレイヤーごとに保持します。この方法で行えば、VercelとSupabaseからKubernetesとRDSへの移行は、一連の設定変更とデータコピーであり、書き直しは決して発生しません。
このスキルの使い方
- プロジェクトの説明を読んでください。不足している情報についてのみ、以下のインテイク質問を1度に行ってください。
references/providers-and-tiers.mdを参照して、レイヤーごとにプロバイダーを選択してください。選択ルールに別の指示がない限り、ティア1から始めてください。- 以下のテンプレートから
docs/PLAN.mdを作成し、references/architecture.mdを参考にした図を含めて、スキャフォールディングの前に提示してください。 - 以下の順序でスキャフォールディングと構築を行ってください。
- ローンチ前に、
references/launch-checklist.mdを実行し、失敗のみを修正内容とともに報告してください。 - 後日トリガーが発火したら、
references/migrations.mdを開き、該当するレイヤーのみを移行してください。同じ週に2つ以上のレイヤーを移行しないでください。
既存のアプリの場合:最初に監査を実施してください。リポジトリを形状にマッピングし、ギャップをリスク順(データ漏洩、障害、悪用、ロックイン、コスト)にリストアップして、そこで止めてください。変更は、オーナーがリストから選択した後に行います。
インテイク
説明で答えられていない質問のみを、1つのメッセージで質問してください。
- ユーザーは誰で、テナント(データを所有する単位:企業、建物、販売店、個人)は何ですか?
- 何が重いですか?フィード、メッセージ、アップロード、動画、イベント、検索?1日あたりのおおよその行数またはファイル数、および成長率。
- Web、iOS、Android、またはそれらの組み合わせ?最初に出荷するのはどれですか?
- リアルタイムのニーズ:チャット、ライブプレゼンス、共同編集、それともポーリングで十分ですか?
- マネタイズ:サブスクリプション、一回払い、マーケットプレイスの支払い、なし?
- 規制対象または機密性の高いもの:保存する支払い情報、医療、未成年者、位置情報、SOC2を要求する政府またはエンタープライズバイヤー?
- 対象ユーザーの地理:単一国か世界規模か?
- 制約事項:既存のクラウドクレジット、既存のプロバイダー、必須の言語。
回答は、references/providers-and-tiers.mdの選択ルールを決定します。
形状
各レイヤーには、役割、大企業のリファレンス、移植性を維持するための1つのルールがあります。ティアごとのベンダーはreferences/providers-and-tiers.mdにあります。
- エッジ:DNS、TLS、CDN、DDoS、WAF、レート制限、ボットフィルタリング、すべてのホストの前面。大企業:Cloudflare、Akamai、Fastly、AWS WAFを備えたCloudFront。ルール:DNSゾーンを所有すること。すべてのプロバイダーはCNAMEの背後に配置されるため、プロバイダーの交換はDNS変更で済みます。
- フロントエンド:独立したデプロイ可能なユニット。静的またはサーバーサイドレンダリング。ビジネスロジックを持たず、データベースアクセスもしません。大企業:コンテナにビルドされ、CDNを通じて提供されるReactまたはNext.jsアプリ。ルール:フロントエンドは標準のNodeコンテナまたは静的バンドルとしてビルドされ、パブリックAPIとのみ通信します。
- ゲートウェイ:エッジからのTLSを終端し、パスでルーティングし、大まかな制限を適用するロードバランサーまたはAPIゲートウェイ。大企業:ALB、Envoy、NGINX Ingress、Kong。ルール:APIは、独自のミドルウェアで再現できないゲートウェイ機能に依存してはなりません。
- バックエンド:ゲートウェイの背後にある1つのモノリスサービス。チームが衝突した場合にのみサービス分割します。大企業:ShopifyやGitHubのRails、InstagramのDjango、NotionのNode、内部はgRPC、外部はGraphQLまたはREST。ルール:ヘルスチェックエンドポイントを持つDockerコンテナ、環境変数からの設定、ビジネスロジックへのベンダーSDKの組み込み禁止。
- ワーカーとキュー:ジョブを消費する独立した長時間実行プロセス。複数のステップや人間の待機があるジョブにはワークフローエンジン。大企業:ShopifyのSidekiqとKafkaコンシューマー、NetflixとDuolingoのTemporal、NotionのKafka。ルール:ジョブはべき等であり、IDを持ち、ブロブは含まず、キューは標準のRedisまたはKafkaプロトコルであること。
- リレーショナルデータベース:記録システムとしての1つのPostgres(またはMySQL)プライマリ。読み取り用のレプリカ。単一マシンの限界を超えた場合のみシャーディング。大企業:PgBouncerを備えたNotionとFigmaのRDS Postgres、Shopifyの100以上のMySQLシャード。ルール:Postgresワイヤプロトコルのみ。リポジトリ内のSQLマイグレーション。SQL内のロールとRLS。特定のプロバイダーのAPIでのみ動作するものは禁止。
- キャッシュ:ホットリード、レート制限カウンター、ロック、セッションのためのRedisまたはMemcached。ルール:標準のRedisプロトコル。キーはテナントスコープかつバージョン管理されていること。アプリはキャッシュが空でも動作する必要があります。
- オブジェクトストレージ:すべてのファイルのためのS3またはS3互換バケット。データベースは使用しません。ルール:S3 APIのみ。キーはテナントをプレフィックスとし、署名付きURLまたはCDNを通じて提供します。
- アイデンティティ:JWTを発行するアイデンティティプロバイダー。アプリが所有する
usersテーブル。大企業:社内ソリューションとエンタープライズSSO用のOktaまたはAuth0。ルール:APIはJWKSを介してトークンを自身で検証し、ユーザーテーブルを所有するため、発行者を変更できます。 - イベントと分析:プロダクト分析、後には変更データキャプチャ(CDC)によって供給されるウェアハウス。大企業:SnowflakeまたはBigQueryへのKafka。ルール:ウェアハウスはデータベースから読み取り、アプリからの二重書き込みは行いません。
- オブザーバビリティ:構造化ログ、エラー、メトリクス、トレース、アップタイム、ランブックにリンクされたアラート。大企業:Datadog、Grafana、Honeycomb、Sentry、OpenTelemetry。ルール:アプリはOpenTelemetryとJSONログを出力するため、バックエンドはエクスポーターの設定で変更可能です。
- デリバリー:プッシュごとのCI、Infrastructure as Code、カナリアまたはブルーグリーンデプロイ、フィーチャーフラグ、高速ロールバック。大企業:Terraform、BuildkiteまたはGitHub Actions、ArgoCDまたはSpinnaker、LaunchDarkly。ルール:ダッシュボードでクリックされたものはすべて、同日中に
infra/に書き留められ、Terraformはティア2から使用します。
移植性ルール
これらにより、後日の移行を低コストにします。MVPサイズではほとんどコストがかからず、週末の移行と四半期にわたる書き直しを分けるものです。
- フロントエンドとバックエンドは、最初のコミットから別々のリポジトリかつ別々のデプロイ可能ユニットとします。バージョン管理されたHTTP APIと共有スキーマを介して通信します。
- バックエンドとワーカーは、コンテナが動作する任意の場所で実行できるDockerイメージとします。APIにサーバーレス関数は使用しません。Vercel関数、Lambdaハンドラー、エッジ関数は、後でコンテナに移行できず、書き直しが必要になる唯一のものです。
- インフラストラクチャとの通信は、標準プロトコルのみを使用します:Postgresワイヤプロトコル、Redisプロトコル、S3 API、インターフェース背後にあるSMTPまたはHTTPメールAPI、トークン用のJWKS、テレメトリー用のOpenTelemetry。プロバイダー独自のクライアントライブラリは、交換可能な薄いアダプターモジュールでのみ許可されます。
- ビジネスロジックにプロバイダー機能を含めません:PostgREST呼び出し、バックエンドでのSupabaseやFirebaseクライアント、Vercel固有のキャッシュAPI、Workers KVは禁止。フロントエンドは、サインインのみにプロバイダーの認証SDKを使用しても構いません。
- アプリは自身のスキーマを所有します:リポジトリ内のSQLマイグレーション、ダッシュボードではなくマイグレーションツールによって適用。ロール、RLS、関数は、任意のPostgresで再実行可能なSQLファイルとします。
- アプリは自身のユーザーを所有します:最初のログイン時にIDプロバイダーからミラーリングされた
usersテーブル。プロバイダーIDは列として保存。権限データはアプリのテーブルに存在します。 - 設定は環境変数であり、起動時に検証されます。シークレットはプラットフォームのシークレットストアに存在しますが、環境変数としてアプリに到達するため、ストアは変更可能です。
- DNSゾーン(Cloudflare)を所有します。すべてのプロバイダーはCNAMEターゲットです。プロバイダーのネームサーバーを直接指すものはありません。
- オブジェクトストレージのキーとバケットレイアウトはR2とS3で同じです。コードはエンドポイント設定付きのS3 SDKを使用します。
- すべてのレイヤーには文書化されたエクスポート方法があります:データベースの
pg_dumpとロジカルレプリケーション、オブジェクトのrclone。Redisダンプは不要です。キャッシュは使い捨て可能であり、キューはドレインされるためです。 - ヘルスチェックエンドポイント、SIGTERMによるグレースフルシャットダウン、水平方向のステートレス性を初日から備えます。RailwayからKubernetesまで、すべてのプラットフォームがこれらに依存するためです。
- テレメトリーとログは初日からOpenTelemetryとJSONです。ベンダーエージェントはコードにインストールしません。
ティア
レイヤーごとに3つのティアがあります。トリガーは測定可能です。ベンダー、コスト、選択ルールを含む完全なテーブルはreferences/providers-and-tiers.mdにあります。
- ティア1、MVP:セットアップに数分かかり、月額約150ドル未満のマネージドプロバイダー。Vercel上のフロントエンド、Railway上のバックエンドコンテナ、Supabase上のPostgres、Railway上のRedis、R2上のオブジェクト、Cloudflare上のエッジ、SentryとBetter Stack。有料の顧客がアップタイムについて尋ねるまで、または以下の数値に達するまで使用します。
- ティア2、成長:重要な部分は、自身のクラウドアカウント上で同じ形状を使用。PostgresはPgBouncerまたはRDS Proxyを備えたRDSまたはAurora Multi AZ、コンテナはECS Fargateまたは小さなEKS、ElastiCache、S3またはR2、すべてにTerraform、読み取りレプリカ、ワークフローにTemporal。トリガー:有料顧客がSLAまたはSOC2を要求した場合、またはデータベースCPUが60%を超える月間アクティブユーザー5,000人が継続した場合、またはPaaS請求額が月額500ドルを超えた場合、または2人目のエンジニアが参加した場合。
- ティア3、スケール:ShopifyやNotionが実行するもの。オートスケーリング付きKubernetes、シャーディングまたはパーティション化されたプライマリ、イベントバックボーンとしてのKafka、CDCによるウェアハウス、マルチリージョン読み取り、DatadogまたはGrafana、プラットフォームチーム。トリガー:継続的な毎秒1,000リクエスト、1TB近くまたはレプリカとキャッシュ後に書き込み制限に達した単一プライマリ、マルチリージョン要件、またはそれを運用する運用チームの存在。
ティアの移行は、一度にすべてのレイヤーではなく、レイヤーごとに行います。通常、データベースが最初に移動し、次にバックエンド、最後にフロントエンドが移動します。フロントエンドをそのままにして最もコストが低いためです。
構築順序
- スキーマ、マイグレーション、ロール、RLS(
references/database.md、references/security.md)。 - ID検証とテナントコンテキストミドルウェア。
- 検証と書き込みのべき等性を備えたコアAPIルート。
- レート制限とキャッシュミドルウェア(
references/rate-limiting.md、references/caching.md)。 - ワーカーとキュー。低速または外部への処理はリクエストパスから外します(
references/jobs-and-queues.md)。 - APIに対するフロントエンド。
- 同じAPIに対するモバイル。
- ログ、メトリクス、トレース、ヘルスチェック、アラート(
references/observability-and-reliability.md)。 - ローンチゲート、予想ピークの3倍でのロードテスト、1回のリストアテスト(
references/launch-checklist.md)。
PLAN.md テンプレート
# <プロジェクト名> 計画
## プロダクトを3文で
## ユーザー、テナント、ロール
## レイヤーごとのプロバイダー(レイヤーごとのティア、理由、それを移行するトリガー、providers-and-tiers.mdから)
## データモデル(テーブル、tenant_idのマーク、インデックス、パーティションテーブル)
## APIサーフェス(リソースごとのルート、認証レベル、レート制限ティア)
## バックグラウンドジョブ(キュー、トリガー、べき等性キー、リトライポリシー)
## サードパーティ(サービス、目的、シークレット名、制限、障害モード)
## キャッシュマップ(内容、キー、TTL、それを無効化する書き込み)
## 脅威モデル(上位5つの悪用ケースとそれぞれの制御策)
## スケール想定(ローンチ時および10倍時のユーザー数、行数、1分あたりのリクエスト数)
## ローンチ時のコスト(プロバイダーごと、月額)
## プロバイダーごとの終了計画(適用されるmigrations.mdのプレイブック、各行に1つ)
## 図
必須ルール
- テナントが所有するすべてのテーブルには
tenant_idが必要。RLSは有効かつ強制。APIは、確認されたメンバーシップからトランザクションごとにテナントを設定し、リクエスト入力からは設定しません。 - クライアントはデータベースにアクセスしたり、特権キーを保持したりしてはなりません。すべてはAPIを通じて行われます。
- すべての入力は境界で検証され、未知のキーは拒否されます。すべてのクエリはパラメータ化されます。
- APIとワーカーは、小さなプールを持つプーラーを介して接続します。ステートメントタイムアウトはロールごとに設定されます。
- レート制限はエッジとAPIに存在し、ユーザー、テナント、IPごとにキーが設定されます。キャッシュキーはテナントスコープかつバージョン管理されます。
- シークレットはプラットフォームストアに、環境ごとに1セット存在します。gitやモバイルバンドルには絶対に含めません。本番環境とステージング環境は、別々のプロジェクトとアカウントです。
- PITRはオンにして、リストアテストを1回実施します。
- Webhookの署名は検証され、リプレイから保護され、べき等であり、2秒以内に応答します。
- すべての外部呼び出しにはタイムアウトを設定。リトライはべき等な処理にのみジッターを付けて行います。失敗したジョブは人間が確認できるようにします。
- リクエストIDとテナントIDはすべてのログ行に含めます。エラー率、p95レイテンシ、5xx数、キューの経過時間、失敗したジョブ、データベース接続に関するアラートを設定します。
モバイル
- 既存のReact NativeまたはExpoアプリ:そのまま維持。
- 新規アプリで、iOSのみまたはiOSファースト:ネイティブSwiftとSwiftUI。大企業は2026年にネイティブに戻りました(ShopifyはSwiftとKotlin、NotionはSwiftUI)。これは、コーディングエージェントが2つ目のコードベースのコストを排除したためです。小規模チームにも同じことが当てはまります。Kotlinは、Androidが実際に構築される場合にのみ使用します。
- 新規アプリで、1人または2人でiOSとAndroidを同日に出荷する必要がある場合:Expo。
- いずれの場合も、アプリはAPIとのみ通信し、トークンをセキュアストレージに保持し、バンドルに秘密を含めません。
リファレンスファイル
references/providers-and-tiers.md:レイヤーごとのテーブル(大企業のプラクティス、ティア1、2、3のベンダー、トリガー、コスト)と、プロジェクトの説明を選択肢に変換する選択ルール。references/migrations.md:各レイヤーを1段階上のティアに移行するためのステップバイステップのプレイブック。references/architecture.md:ティアラベル、3つのリクエストパス、リポジトリレイアウト、環境、エッジとプラットフォームの設定を示す図。references/security.md:テナンシーとRLS、アイデンティティ、シークレット、ヘッダー、入力、アップロード、Webhook、暗号化、削除とエクスポート、モバイル、監査ログ、インシデント。references/rate-limiting.md:数値を含む4つのレイヤーとミドルウェア。references/caching.md:すべてのキャッシュレイヤー、キースキーマ、TTL、無効化、スタンピード保護。references/database.md:スキーマルール、ロール、プーリング、マイグレーション、バックアップ、リストア。
翻訳に関する注意:原文のMarkdown構造、コードブロック、ファイルパス、環境変数名、URL、インラインコードはそのまま保持されています。