モバイルAPI向けのJSONとProtobuf:サイズ・互換性・デバッグ
モバイルAPIでのJSONとProtobufを比較。ペイロードサイズ、互換性、デバッグのトレードオフと、テキストかバイナリかを選ぶ実践的なルールを解説します。
実ユーザーをブロックせずに不正利用を防ぐパブリックAPI向けレート制限:実用的な上限、キー単位クオータ、ロックアウト、導入のコツ。

Retry-After ヘッダーを追加することです。簡単なクライアントでも正しく待てます。\n\n少数のヘッダーを用意しておくと、制限が自明になります。名前を一貫させ、成功レスポンス(クライアントが自分でペース配分できるように)と 429 レスポンスの両方に含めてください:\n\n- Retry-After: 再試行までの秒数\n- X-RateLimit-Limit: 現在のウィンドウで許可されるリクエスト数\n- X-RateLimit-Remaining: 現在のウィンドウで残っているリクエスト数\n- X-RateLimit-Reset: ウィンドウがリセットされる時刻(エポック秒またはISO時刻)\n- X-RateLimit-Policy: "60 requests per 60s" のような短い説明\n\nエラーボディは成功レスポンスと同じくらい構造化しておきます。一般的なパターンは、安定した code、人間向けの message、回復のヒントを含むエラーオブジェクトです。\n\njson\n{\n "error": {\n "code": "rate_limit_exceeded",\n "message": "Too many requests. Please retry after 12 seconds.",\n "retry_after_seconds": 12,\n "limit": 60,\n "remaining": 0,\n "reset_at": "2026-01-25T12:34:56Z"\n }\n}\n\n\nクライアントに 429 を見たらどうバックオフするかを伝えましょう。指数バックオフ(1s、2s、4s、上限は 30〜60 秒など)は良いデフォルトです。いつ再試行を止めるべきかも明示しておくと親切です。\n\nクオータに近づいているとき(例えば 80〜90%)は警告フィールドやヘッダーで事前に通知して、クライアントが失敗する前に速度を落とせるようにしてください。これは特に一つのスクリプトが複数ルートに短時間でアクセスして予想より早く予算を使い切る場合に重要です。\n\n## ステップバイステップ:制限とクオータの簡単な導入計画\n\n制限は一度きりのファイアウォール設定ではなく、プロダクトの挙動として扱うと導入がうまくいきます。目的は変わらず:バックエンドを守りながら通常の顧客を動かし続けること。\n\nまずはクイックインベントリから。すべてのエンドポイントを列挙し、コスト(CPU、DB、サードパーティ呼び出し)とリスク(ログイン、パスワードリセット、検索、ファイルアップロード)でマークします。これにより一律の制限を避けられます。\n\n導入順の例:\n\n- エンドポイントをコストとリスクでタグ付けし、厳格にすべきもの(ログイン、バルクエクスポート)を決める。\n- 識別キーの優先順位を決める:まず API キー、次にユーザーID、最後にIP をフォールバックとして。\n- 短いウィンドウの制限(10 秒単位や分単位)を追加してバーストとスクリプトを止める。\n- 長いウィンドウのクオータ(時間単位や日単位)を追加して持続的な利用を抑える。\n- 運用用のモニタや信頼できるシステムのために許可リストを用意し、業務に支障が出ないようにする。\n\n最初のリリースは保守的に始めましょう。後から緩和する方が、怒ったユーザーを解除するよりずっと簡単です。\n\n監視と調整を続け、ポリシーにバージョン管理を導入してください。どれだけのリクエストが制限に引っかかったか、どのエンドポイントがトリガーしたか、どのキーが影響を受けたかを追跡します。数値を変えるときは API 変更のように扱い、文書化し段階的に展開し、新旧ルールを分けてロールバックを容易にします。\n\nAppMaster でAPIを作るなら、エンドポイントとビジネスロジックに沿ってこれらのルールを設計することで、各ワークフローの実コストに合わせた制限ができます。\n\n## ドラマを起こさないロックアウトワークフロー\n\nロックアウトはシートベルトのような役割です。明らかな不正を素早く止めつつ、通常のユーザーには明確な復旧方法を残すべきです。\n\n落ち着いたアプローチは段階的なペナルティです。クライアントが悪意あるとは限らない(設定ミスかもしれない)と仮定し、同じパターンが繰り返されたときだけエスカレートします。\n\n### シンプルな進行階段\n\n実装と説明が簡単な少数ステップを使いましょう:\n\n- 警告:キーが上限に近づいていることとリセット時刻を通知。\n- 減速:そのキーに対して短い遅延や秒間上限の強化を適用。\n- 一時ロックアウト:数分単位のブロック(時間ではなく分)と正確な解除時刻を返す。\n- 長めのロックアウト:複数ウィンドウに渡る繰り返しがあった場合に適用。\n- 手動レビュー:意図的と思われるパターンや繰り返しの場合の最終手段。\n\n何をロックするかも重要です。API キーごとが通常は最も公平で、呼び出し元をターゲットにできます。アカウントごとはキーを回転した場合に有用です。匿名トラフィックには IP ごとを使うと誤検知が増えます。深刻な不正の場合は複合シグナル(キーをロックしつつその IP に対して追加のチェックを要求する)を使ってもよいですが、影響範囲は小さく保ちましょう。\n\nロックアウトは時間ベースにしてシンプルなルールにします:「14:05 UTC までブロック」「30 分の良好な挙動でリセット」など。自動化されたシステムに対して永続的な禁止は避けてください。バグのあるクライアントはループして短時間で上限を使い切ることがあるので、ペナルティは時間とともに減衰するように設計します。低レートの持続期間を置けばペナルティ段階を下げる、という具合です。\n\nAppMaster でAPIを構築しているなら、この階段はストアドカウンタと Business Process による判定(allow, slow, block)とキーの解除時刻の書き込みで簡単に実装できます。\n\n繰り返しの違反者には手動レビューの流れを用意してください。ユーザーと争わないこと。リクエストID、タイムスタンプ、APIキー名を求めて証拠に基づいて判断します。\n\n## 誤検知を招く一般的なミス\n\n誤検知は防御が通常のユーザーをブロックしてしまう状況です。ルールが実際の利用に対して単純すぎると起こります。\n\n典型的なミスはすべてに同じグローバル制限を適用することです。安価な読み取りと高コストなエクスポートを同じ扱いにすると、安価な方を過剰に守るか、高コストの方を守れないかの二択になります。エンドポイントのコストで分け、重い経路には厳しい制限を設けましょう。\n\nIP のみの制限も落とし穴です。多くの実ユーザーが1つのパブリックIPを共有している(オフィス、学校、モバイルキャリア)ため、一人の重い利用者が皆をブロックすることになります。まずは API キーごとの制限を優先し、IP は明らかな悪用の二次信号としてください。\n\nリミッタの障害も誤検知を生みます。リミッタストアが落ちたときに「閉じる(fail closed)」にすると API 全体が落ちます。「開く(fail open)」にするとスパイクを招く可能性があります。明確なフォールバックを選び、エッジで小さな緊急キャップを維持し、非クリティカルなエンドポイントはグレースフルに劣化させましょう。\n\nクライアント側の扱いも大切です。汎用的な 429 を返すとユーザーはさらにリトライして状況を悪化させます。必ず Retry-After を返し、エラーテキストは具体的に("このキーのリクエストが多すぎます。30 秒後に再試行してください。")してください。\n\n最も避けやすい問題は秘密主義です。制限が非公開だと、顧客が本番負荷で初めて当たったときにそれをバグだと感じます。シンプルなポリシーを共有し、安定させておきましょう。\n\n誤検知を避けるための簡単チェックリスト:\n\n- 高コストと低コストのエンドポイントで制限を分離する\n- 優先的に API キーで制限し、IP のみにはしない\n- リミッタが利用不可の時の挙動を定義する\n- 明確な Retry-After を含む 429 レスポンス\n- 制限を文書化し、実施前に告知する\n\nAppMaster を使っている場合は、エンドポイントごとに別のキャップを設定し、一貫したエラーペイロードを返すことでクライアントが推測なしにバックオフできるようにしましょう。\n\n## 実用的な監視とアラート\n\nレート制限が機能するには、リアルタイムで何が起きているか見えることが前提です。目標はすべてのスパイクを捉えることではなく、障害や顧客の不満につながるパターンを早期に発見することです。\n\nボリュームと意図の両方を説明する小さな信号セットから始めましょう:\n\n- 分ごとのリクエスト数(全体とキーごと)\n- 429 発生率(スロットルされたリクエスト)と 5xx 発生率(バックエンドの痛み)\n- 401/403 の繰り返し(キー不正、認証情報の詰め、クライアント設定ミス)\n- ボリュームやコストで上位のエンドポイント(遅いクエリ、重いエクスポート)\n- 突然トップ10に現れた未知のエンドポイント\n\n「悪いトラフィック」と「新機能・リリースによる増加」を分けるために、ダッシュボードにデプロイ時間、フィーチャーフラグ、マーケティング送信のコンテキストを加えてください。リリース直後にトラフィックが跳ね上がり、429/5xx の比率が安定していれば成長の可能性が高いです。特定のキー、IPレンジ、重いエンドポイントに集中しているなら疑わしい行動として扱います。\n\nアラートは退屈で良いです。閾値とクールダウンを使って同じイベントで毎分ページが飛ばないようにします:\n\n- 429 発生率が X% を超え 10 分続く場合、1 時間に1回通知\n- 5xx が Y% を超え 5 分続く場合、即時ページング\n- 単一キーがクオータを Z% 超過して 15 分続く場合、調査を開始\n- 401/403 が分あたり N を超える場合、不正の可能性としてフラグ\n\nアラートが出たら短いインシデントノートを残してください:何が変わったか、観測したもの(上位キー/エンドポイント)、調整した内容(制限、キャッシュ、一時ブロック)。これらのノートが時間とともに実際のプレイブックになります。\n\n例:新しい検索エンドポイントをローンチしてトラフィックが倍増したとします。もし多くの呼び出しが多くのキーに分散しているなら、キーごとのクオータを少し上げてエンドポイントを最適化します。もし一つのキーがエクスポートを延々と叩いて遅延を引き起こしているなら、そのエンドポイントだけ別枠で上限を設け、所有者に連絡します。\n\n## ローンチ前後の簡単チェックリスト\n\nうまく動いているときは設定は退屈です。このチェックリストは誤検知や明白なギャップを検出します。\n\n### 新しいエンドポイントをリリースする前に\n\nステージングで、そしてリリース直後に以下を確認してください:\n\n- 識別:リミッタが正しいキーで動作しているか(まず API キー、その後ユーザーやIP)、キー回転時に古いペナルティが引き継がれないか。\n- 制限:デフォルトのキー単位クオータを設定し、エンドポイントのコストに応じて調整(安価な読み取り vs 高コストな書き込み)。\n- レスポンス:安定したステータスと回復情報(再試行時間、残り予算、安定したエラーコード)を返す。\n- ログ:誰が制限されたか(キー/ユーザー/IP)、どのルートで、どのルールが発火したか、サポート用のリクエストIDを記録する。\n- バイパス:モニタや信頼できる統合のための緊急許可リストを保持する。\n\nAppMaster 上で構築しているなら、新しい API エンドポイントごとにコスト層を決めるのが有効です:単純なルックアップは寛容に、重いビジネスロジックを呼ぶものは最初から厳しく。\n\n### インシデント発生時(不正または突然のトラフィック増)\n\nバックエンドを守りつつ実ユーザーが回復できるように:\n\n- リスクの低いルート(多くは読み取り)だけ一時的に上限を上げてエラー率を監視。\n- 調査中は既知の良い顧客のために短期間の許可リストを追加。\n- グローバルな制限を下げるのではなく、リスクのある特定ルートを締める。\n- 共有ネットワークをブロックしないために強い識別(API キー必須、IP 依存を減らす)を有効にする。\n- サンプルを取得:上位キー、上位IP、ユーザーエージェント、ペイロードパターン。\n\n顧客のために上限を上げる前に、その顧客の通常のリクエストパターン、エンドポイントの構成、バッチ化やバックオフが可能かを確認し、キー共有をしていないかを確かめてください。\n\n月次レビューでは:上位で制限にかかるエンドポイント、トラフィックに対する制限ヒット率、高コスト新規ルート、クオータが実利用に合っているかをチェックします。\n\n## 例:実際のパブリックAPIをユーザーを壊さずに守る\n\nあなたが運営するパブリックAPIが、顧客ポータル(高ボリューム、安定したトラフィック)と内部管理ツール(低トラフィックだが強力な操作)で使われていると想像してください。両方とも API キーを使い、ポータルはエンドユーザー向けにログインエンドポイントも持っています。\n\nある午後、パートナーがバグのある統合を出荷します。失敗したリクエストを短時間で再試行するループが発生し、単一の API キーから毎秒 200 リクエスト送られ始めます。ガードレールがなければ、そのキー一つで他のすべてを圧迫してしまいます。\n\nキー単位の制限があれば影響範囲は抑えられます。問題のキーが分単位の上限に達して 429 を受け取り、他の顧客は通常通り動作し続けます。さらにエクスポートのような高コストなエンドポイントには別に低い上限を設けておけば、「許可された」トラフィックであってもデータベースを過負荷にすることはできません。\n\n同時に、認証エンドポイントに対する総当たり攻撃が始まったとします。共有IPレンジ全体をブロックする代わりに、その挙動に合わせて遅延を入れ、アカウントあたりの失敗試行数と短いウィンドウの IP ごとの指標に基づいて段階的にロックアウトします。攻撃者は次第に長い待ち時間を受け、最終的に一時的にロックされます。\n\n誤ってパスワードを数回間違えた実在の顧客は回復できます。あなたのレスポンスが明確で予測可能だからです:\n\n- Retry-After を含む 429 でクライアントがいつ再試行できるかが分かる\n- 短いロックアウト(例えば 10〜15 分)で恒久的な禁止ではない\n- アカウントの存在を漏らさない一貫したエラーメッセージ\n\n対応の確認には以下のメトリクスを見ます:\n\n- API キーとエンドポイントごとの 429 発生率\n- 認証失敗率とロックアウト数\n- インシデント時の P95 レイテンシと DB CPU 使用率\n- 影響を受けたユニークキー数(小さくあるべき)\n\nこれが、バックエンドを守りながら通常のユーザーを罰しない保護的なレート制限の例です。\n\n## 次のステップ:小さなポリシーを作って反復する\n\n初日から完璧なモデルは不要です。小さく明確なポリシーを始めて、実際のユーザーの挙動を学びながら改善してください。\n\nしっかりした最初のバージョンは通常次の3つを含みます:\n\n- ほとんどのエンドポイントをカバーするキー単位のベースライン(分あたりリクエスト数)\n- 高コストエンドポイント(検索、エクスポート、ファイルアップロード、複雑なレポート)への厳しい上限\n- クライアントに次の行動を示す短いメッセージを含む明確な 429 レスポンス\n\nロックアウトは不正リスクが高く意図が推測しやすい場合にのみ導入します。サインアップ、ログイン、パスワードリセット、トークン作成などが典型的な候補です。ロックアウトは最初は短めに(分単位)、段階的な摩擦を優先:遅延、短期ブロック、その後に強いチェックを要求する、という順序にします。\n\nサポートがエンジニアの助けなしに説明できるよう、ポリシーを平易な言葉で文書化してください。何を制限するか(API キーごと、IP ごと、アカウントごと)、リセットウィンドウ、顧客の回復方法を含めます。\n\n新しいバックエンドを実装する際にこれをやるなら、AppMaster は実用的な選択肢になり得ます:API を作り、カウンタやロックアウト判定を含むビジネスワークフローを視覚的に定義してクラウドにデプロイしたり、必要に応じて生成されたソースコードをエクスポートして完全な制御を得ることができます。