maintainable-app について
maintainable-appは、本番アプリケーションの開発・変更・レビューを支援するスキルです。冪等性、上限付きリトライ、復旧経路、可観測性を重視し、一般的な障害への自動対応を促します。
主な機能
- 01本番環境の障害要因の特定
- 02冪等な処理と作業キーの設計
- 03タイムアウトと上限付きリトライ
- 04キューと分散ワークフローの復旧設計
- 05状態遷移に沿った可観測性の実装
活用シーン
- 01Webhook、キュージョブ、定期処理の設計
- 02外部APIのタイムアウトとリトライへの対応
- 03アプリの復旧手順と運用シグナルのレビュー
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jpcaparas/ skills --skill maintainable-appインストール後、Claude Code で/maintainable-appを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
AGENTS.mdmetadata.jsonREADME.mdskill-card.prompt.mdagents/openai.yamlassets/.gitkeepevals/evals.jsonreferences/distributed-systems.mdgotchas.mdjobs-and-queues.mdobservability.mdprinciples.mdreview-rubric.mdsource-notes.mdscripts/analyze_app_resilience.pytest_skill.pyvalidate.pytemplates/resilience-review.md詳細
保守しやすいアプリ
一般的な本番障害から自動的に復旧し、意図的に機能を縮退させ、何が起きたのかを担当者が一人でも把握できるだけの情報を残すアプリケーションを構築、編集、レビューします。
パッシブトリガー
本番環境に関わるアプリケーション、バックグラウンドワーカー、スケジュールタスク、Webhook、決済フロー、インポート/エクスポート、通知、API 連携、データベースの状態遷移、キャッシュ、ファイルアップロード、キュー、cron、認証/セッションフロー、オブザーバビリティ、ログ記録、トレース、アラート、または信頼性に関わる動作に影響するコーディングタスクでは、このスキルをバックグラウンドで読み込んでください。
小規模な変更では軽量に扱います。障害モードを手短に確認して、実装に影響するフェイルセーフ、エッジケース、オブザーバビリティに関する判断だけを伝えてください。また、利用可能であれば、ソースコードの変更には {{ skill:maintainable-code }} を、テストの追加や変更には {{ skill:maintainable-tests }} も読み込んでください。
判断ツリー
何を構築または変更しますか?
-
ユーザー向けのリクエスト、ワークフロー、または状態遷移:
references/principles.mdを読んでください。通常の成功経路を実装する前に、障害状態、リトライの安全性、ユーザーに見えるフォールバック、復旧経路を定義してください。 -
キュー、バックグラウンドジョブ、cron、Webhook、インポート/エクスポート、メール、決済のキャプチャ、または通知:
references/jobs-and-queues.mdを読んでください。冪等性、作業の一意な識別、同時実行数の上限、リトライ回数の上限、デッドレター処理、古い作業の復旧、ワーカーのタイムアウトを必須としてください。 -
複数のサービス、外部 API、イベントの発行、分散データの変更、または非同期ワークフロー:
references/distributed-systems.mdを読んでください。タイムアウト、リトライ予算、アウトボックス/インボックス処理、重複排除、照合、補償アクションを設計してください。 -
ログ、メトリクス、トレース、アラート、ダッシュボード、またはインシデントの診断:
references/observability.mdを読んでください。すべてのコード行ではなく、ユーザーへの影響と復旧を説明できる判断ポイントを計測してください。 -
差分または実装計画のレビュー:
references/review-rubric.mdを使用してください。開発者の手動対応が必要になる障害、副作用の重複、停滞状態、上限のないリトライ、運用上のシグナル不足を優先して指摘してください。 -
どこから始めればよいか分からない:
references/principles.mdを読んでから、以下のセルフヒーリングゲートを実行してください。
クイックリファレンス
| 状況 | デフォルトの対応 |
|---|---|
| ブラウザーからの送信の重複、Webhook の再送、リトライ、またはワーカーの再起動 | 冪等性キーまたは決定的な作業キーを追加し、結果または状態遷移を永続化します |
| 10 人のユーザーが同じ高負荷ジョブを起動する | 一意なジョブキーで処理を集約し、稼働中のワーカーを 1 つだけ確保し、既存のジョブ状態を返して、進捗を公開します |
ジョブが pending または running のまま長時間経過する | expires_at またはハートビートに基づく古い状態の検出、安全なリトライまたはフェイルオーバー、監査ログの記録を追加します |
| リモート API 呼び出し | 接続タイムアウトとリクエストタイムアウトを設定し、リトライ可能なエラーを分類し、ジッターを加えた上限付きバックオフを使用して、リトライ予算に達したら停止します |
| キュー負荷の急増 | 作業をバッファーし、ワーカーの同時実行数を制限し、バックプレッシャー/レート制限を適用して、共有依存先を保護します |
| データベース書き込み後の副作用 | アウトボックスまたはトランザクションによる引き渡しを使用し、コンシューマーを冪等にします |
| 複数ステップの分散ワークフロー | 状態を明示的にモデル化し、照合または補償アクションを追加します |
| 部分的な障害 | 価値の低い機能から先に縮退させ、ユーザーの主要なタスクを維持します |
| リクエスト/ジョブの進捗をログに記録する | 相関 ID、実行主体、作業キー、状態遷移、試行回数、依存先、所要時間、結果を含めます |
| メトリクス | レイテンシー、トラフィック、エラー、飽和度、キュー滞留時間、リトライ回数、デッドレター件数、古い作業を追跡します |
| トレース | 小さなローカルヘルパーではなく、境界をまたぐ呼び出しと永続化される非同期の引き渡しにスパンを追加します |
| アラート | ユーザーへの影響がある場合、または自動化を使い切った場合のみページングし、それ以外は確認可能なダッシュボードやチケットを作成します |
コアのルール
- リトライ、重複配信、並行処理、遅延、部分的な障害、デプロイ時の再起動、古い状態は、例外的な事故ではなく通常の入力として扱います。
- コストの高い操作や副作用を伴う操作には、すべて安定した識別子を付与します。システムは、リクエストが新しい処理なのか、再送なのか、それとも異なる意図なのかを判別できる必要があります。
- 曖昧なステータス文字列よりも、明示的な状態機械を優先します。各状態には、許可される遷移、担当者、タイムアウト、リトライポリシー、終端状態、復旧動作が必要です。
- 人間向けの運用手順書に頼る前に、アプリケーション内に復旧の仕組みを用意します。上限付きリトライ、古い処理を検出するスイーパー、調整ジョブ、デッドレターキュー、安全な再実行経路を活用します。
- キュー、リース、レート制限、バルクヘッド、バックプレッシャーで影響範囲を制限します。ひとつの負荷の高いワークフローによって、アプリ全体のリソースが枯渇しないようにします。
- 副作用は、それを確実に制御できる境界で冪等にします。データベース制約、一意キー、冪等性テーブル、アウトボックス/インボックステーブル、プロバイダーの冪等性キー、キューの重複排除などを利用します。
- 処理がプロセス、ネットワーク、キュー、データベース、プロバイダーの境界を越える箇所には、すべてタイムアウトを設定します。依存先の停止は、復旧経路に上限を設けた既知の状態として扱います。
- 黄金律:本番環境に影響するアプリの変更では、まず4つのゴールデンシグナル、すなわちレイテンシ、トラフィック、エラー、飽和状態を考慮します。ユーザーの健全性と容量に関するこれらの問いに対応した後で、個別のメトリクスを追加します。
- 判断、状態遷移、リトライ、破棄された処理、縮退動作、依存関係の境界を記録・トレースします。本番環境に関する問いに答えられないテレメトリは追加しません。
- ログは安全に保持し、検索できる状態にします。シークレット、トークン、生の決済情報、完全な個人識別情報(PII)、セッションクッキー、プロバイダーの認証情報は、決してログに記録しません。
- 復旧経路をテストします。重複リクエスト、リトライ可能な障害、停止したジョブ、依存先のタイムアウト、古い状態について、対象を絞った検証または文書化された未対応事項がない限り、その機能は運用可能な状態ではありません。
自己修復ゲート
アプリの変更を完了する前に、次の項目を確認します。
| ゲート | 合格条件 |
|---|---|
| 識別子 | 重複リクエスト、ジョブ、Webhook、イベントが、安定した冪等性キーまたは処理キーに対応付けられている |
| 状態 | 複雑な処理に、明示的な保留中/実行中/成功/失敗/キャンセル/古い状態の動作がある |
| 並行処理 | 共有リソースに、一意性、ロック、リース、レート制限、またはワーカー数の上限が設定されている |
| 時間 | リモート呼び出し、ジョブ、ロック、保留中の状態に、タイムアウトまたは有効期限が設定されている |
| リトライ | リトライ可能なエラーが分類され、回数が制限され、ジッターが適用され、重複した副作用が起きないよう安全に処理されている |
| 復旧 | 開発者が手作業でデータを編集しなくても、停止中、一部失敗、失敗の各状態から、リトライ、調整、再実行、または終端化ができる |
| 縮退 | オプションの依存先が失敗しても、アプリがユーザーにとって最も重要なタスクを維持できる |
| 可観測性 | ログ、メトリクス、トレースから、ユーザーへの影響、処理の識別子、状態遷移、試行回数、依存先の健全性、復旧結果が分かる |
| アラート | 想定内の一時的な障害が発生するたびではなく、自動化の試行が尽きたとき、またはユーザーに影響が及んだときにアラートが発報される |
| テスト | 本番環境で最も起こりやすい障害に対し、対象を絞ったテスト、シミュレーション、または明記された検証上の未対応事項がある |
運用ワークフロー
-
まず周辺を調査します。 耐障害性を設計する前に、周辺のハンドラー、ジョブ、スキーマ、プロバイダーアダプター、キュー設定、ロギング規約、ダッシュボード、テストを読みます。
-
障害マップを作成します。 重複入力、同時入力、依存先のタイムアウト、プロバイダーの 429/5xx、ワーカーのクラッシュ、デプロイ時の再起動、データベースの競合、古い状態、部分的な完了を列挙します。機能のリスクに見合った規模にとどめます。
-
復旧の担当を決めます。 各復旧経路を、リクエストハンドラー、キューワーカー、スケジューラー、調整ジョブ、データベース制約、プロバイダーの冪等性機能、運用者向けツールのどれが担うかを決定します。
-
最小限の永続的な仕組みを実装します。 ローカルな制約と既存のフレームワークプリミティブを優先します。障害モードが導入を正当化できるほど現実的な場合は、キュー、ロック、アウトボックステーブル、サーキットブレーカー、ウォッチドッグを追加します。
-
状況を計測できるようにします。 状態遷移と境界で構造化ログ、メトリクス、スパンを追加します。それぞれのシグナルが答える具体的な問いを明確にします。
-
障害時の動作を検証します。 実用的な範囲で、重複入力、再試行、タイムアウト、古い作業、依存先の機能低下時の動作について、対象を絞ったテストやローカルシミュレーションを実行します。
-
明確に報告します。 対応したエッジケース、追加したフェイルセーフ、追加したシグナル、実施した検証、残る運用上のリスクを明記します。
オプションのヘルパー
このヘルパーは、迅速なレビュー用のプロンプトスキャナーとして使い、判定そのものとしては扱わないでください。
python3 scripts/analyze_app_resilience.py /path/to/project
python3 scripts/analyze_app_resilience.py /path/to/project --json
冪等性の欠落、再試行/バックオフの不備、明確なタイムアウトのない外部呼び出し、コンテキストの少ないログ、握りつぶされたエラー、復旧手段のない保留状態を検出します。スキャンで何も検出されなくてもアプリの耐障害性が証明されるわけではなく、多く検出されてもコードに誤りがあるとは限りません。
読み方ガイド
| 必要な情報 | 参照先 |
|---|---|
| 自己修復の基本原則と障害マッピング | references/principles.md |
| ジョブ、キュー、Webhook、cron、停止した作業、重複した作業 | references/jobs-and-queues.md |
| 再試行、タイムアウト、冪等な API、アウトボックス/インボックス、サーガ、調整 | references/distributed-systems.md |
| ロギング、メトリクス、トレーシング、アラート、ダッシュボード | references/observability.md |
| 耐障害性に関する差分を重大度優先でレビュー | references/review-rubric.md |
| よくある落とし穴とアンチパターン | references/gotchas.md |
| 調査資料と適用に関する注記 | references/source-notes.md |
落とし穴
- 安全でない作業を再試行すると、復旧させようとしていた障害を引き起こす可能性があります。再試行を追加する前に、操作を冪等にしてください。
- ワーカーの処理完了前にロックが期限切れになる場合、ジョブが一意であるだけでは不十分です。ロックの TTL、ジョブのタイムアウト、可視性タイムアウト、再試行の期間を合わせてください。
pendingは復旧戦略ではありません。終端状態ではないすべての状態に担当者と、古い状態への対処経路が必要です。- 相関 ID、作業キー、試行回数、結果のないログは、メンテナーが一人の状況でインシデントが発生した際にほとんど役に立ちません。
- 可観測性を高めれば自動的に良くなるわけではありません。カーディナリティが高いテレメトリー、シークレットを含むテレメトリー、クエリされないテレメトリーは、復旧を改善せずにコストとリスクを生みます。
- デッドレターキューはゴミ箱ではありません。アラーム、検査用フィールド、再投入ルール、不正なメッセージへの対処方針が必要です。
- 段階的縮退は障害が起きる前に実装する必要があります。コアタスクが引き続き動作するように、オプション機能の障害は最小限に抑えてください。