APIバージョン管理と契約の互換性
TL;DR(ドクター)
互換性は規律であり、運ではありません。明確なバージョンポリシー(SemVer)を維持し、数学(何が「壊れた」のか、何がないのか)、契約テスト、スキーマレジスタ、およびSunsetプロシージャを変更します。マネーとコンプライアンスのために-vN付きの厳格なREST/gRPC、 UI集計のために-進化的GraphQLと'@deprecated'。常に:カナリアトラフィック、下位互換性≥ 1つのリリースサイクル、移行ガイド、フィールドテレメトリ。
1)基本的な概念と目標
下位互換性(BC):古いクライアントは新しいサーバーに適しています。
Forwards-compatible (FC):新しいクライアントは古いサーバに適しています(制限あり)。
ワイヤー互換性:「ワイヤー」のフォーマットは壊れません(gRPC/Protobufのために特に重要)。
SemVer: 'MAJOR。マイナー。PATCH'-契約を破る→MAJORを上げる。
目標は、破壊的な変更を最小限に抑え、予測可能な移行ウィンドウを提供することです。
2)変更行列: できることとできないこと
3)異なるAPIスタイルのポリシー
3.1 REST
URIのバージョン('/v1/……')またはドメイン('api-v1。').ヘッダーのバージョン-内部ケースのみ。
追加、削除しないでください:新しいフィールド-ok、古い-ダイアグラムの「非推奨」としてマークし、少なくとも1つのサイクルを残します。
ステータス/エラー: コードと構造のエラーを変更しないでください。コード/エラー。メッセージ/エラー。詳細はこちら'.
Idempotencyは変更されていません:'Idempotency-Key'を持つ安全な'POST'を'行動的に異なる'チャレンジにしないでください。
3.2 gRPC/Protobuf
フィールド番号は神聖です:削除された番号を再利用しないでください。
新しいオプション/repitフィールドを追加するだけです。「hard必須」-検証を通じて、'required'ではありません。
バージョンパッケージ:'支払い。v1'、'支払い。v2'。
サービス互換性:新しいRPC→新しい方法;古いものの振る舞いは変えません。
proto message Payout {
reserved 4 ;//field deleted, number reserved string id = 1;
string currency = 2;
int64 amount_minor = 3;
// v2: optional string comment = 5;
}
3.3 GraphQL
v2のない進化:フィールド/タイプを追加します。削除-ウィンドウのアナウンスで'@deprecated (reason)'を通じて。
Persisted Queries:パブリッククライアントの場合、クエリのホワイトリストを使用します。互換性を制御する方が簡単です。
フィールドレベルのauthZとテレメトリー:削除する前に実際にどのフィールドが使用されているかを知る。
graphql type Payout {
id: ID!
amountMinor: Long!
currency: String!
comment: String @deprecated(reason: "Use note")
note: String
}
3.4 Webhook
パス内のバージョン('/webhooks/v1/payments')と固定イベントエンベロープ('event_id'、'type'、'ts'、'data')。
署名/NMASを変更しないでください。新しいアルゴリズム-フラグ付きのオプションとして。
拡張機能-新しいフィールドのデータのみを使用します。'と'headers'-古いものを削除せずに。
4)ゲートウェイAPIとバージョンルーティング
ルールベースのルーティング:接頭辞'/v1'、ヘッダ'X-Api-Version'、ドメイン。
Shadow/Canary:新しいバージョンのプロダクショントラフィックの一部を「影に」反映し、答えを比較します。
バージョンごとのレート/クォータ:移行中に古いクライアントを保護します。
- 'Sunset:
'-バージョンのシャットダウン日 - 'Deprecation: true'-バージョンが廃止される
- 'Link:
;rel=「deprecation」'-changelog/migrationガイド
nginx location ~ ^/v2/ {
proxy_pass http://api_v2;
}
location ~ ^/v1/ {
add_header Deprecation "true";
add_header Sunset "Thu, 01 May 2026 00:00:00 GMT";
proxy_pass http://api_v1;
}
5)スキーム登録と契約
OpenAPI/JSONスキーマREST;Protobuf descriptorsのGRPC;SDL レジストリグラフQL。
CIチェック:PRでlinters+「breaking-changes check」。
消費者主導の契約(CDC):消費者テスト(Pact/analog)-目立たない休憩に対する保護。
Changelog: machine-readable(例えば、'CHANGELOG。レジストリ内のmd'+リリースノート)。
6)フィールドの進化: 親指のルール
ID/keys:新しいフィールド'_v2'と遷移期間なしでフォーマット(UUID↔int)を変更しないでください。
時間/通貨:UTC ISO-8601/epochとamount_minor+通貨を維持します。スケールしないでください(ペニー/セント)。
Enum:値を追加-ok;古いものの意味を変えるな。RESTの場合、intではなく文字列の値を与えます。
ペジネーション:カーソルベースのより安定した;カーソルの意味を変更しないでください。
7)枯渇と「日没」の手順
1.発表(T-90/60): changelog、パートナーへの郵送、'Deprecation/Sunset'の見出し。
2.重複した期間:V1およびV2は並行して作動します;V1には、応答/ログの警告が装備されています。
3.使用テレメトリー:他に誰がV1を呼び出しますか?ポイントコンタクト。
4.V1のフリーズ:バグ修正のみ/機能なし。
5.Sunset-410 Goneまたはmigration命令ブロックページ。
8)痛みのないリリース: 戦略を立てる
青/緑または重み付けルーティング:1-5-25-50-100%トラフィック。
互換性ウィンドウ:少なくとも1-2マイナーリリース、より頻繁に6-12外部APIのための月。
機能アップグレードせずに新しいロジックフィールド/ブランチを含めるフラグ。
読み取り/書き込み分割:最初に新しいフィールドを読み取るためのサポートを追加してから、書き込みを開始します。
9)相互運用性試験(練習スイート)
古いバージョンからの応答のゴールデンテスト。
回路の差分テスト:CIの破損はありません。
リプレイ生産はV2(シャドウ)のステージングで実行されます。
Back/Forwardスクリプト:古いサーバー上の新しいクライアントとその逆(FCが有効な場合)。
Webhookの契約テスト:署名、フォーマット、時間の検証。
10)バージョン管理プロセスのメトリックとSLO
最後のMINORの顧客の%(目標≥日没前の80%)。
リリースあたりの互換性/使用不能エラー(ターゲット0)。
レガシーコールのシェア(日没まで減少)。
クライアント移行時間(中央値/p95)。
バージョン間のレイテンシ/リグレッションデルタ(基本的なものより悪くない)。
11)アーティファクトの例
OpenAPI (fragment、 field depriction):yaml components:
schemas:
Payout:
type: object properties:
id: { type: string, format: uuid }
amount_minor: { type: integer }
currency: { type: string }
comment:
type: string deprecated: true description: "Use note"
note: { type: string }
Protobuf(予約済みおよびv2パケット):
proto syntax = "proto3";
package payouts. v1;
message Payout { reserved 5; string id=1; int64 amount_minor=2; string currency=3; }
GraphQL(枯渇):
graphql type Query { payout(id: ID!): Payout }
12)隣接するチャンネルのバージョン管理
SDK/CLI: SemVer+APIバージョン依存性、READMEで規定された互換性。
イベント/ストリーム(WS/Kafka): version in 'envelope。バージョン';新しい属性-オプション;dedupとresumesはバージョン間で同じ動作をします。
Reporting/CSV:ファイル名/ヘッダーのバージョン;右側に列を追加すると、順序/タイプは変更されません。
13)ガバナンスと役割
契約所有者(ドメイン所有者)、Steward API(ルールとlinters)、 Release Manager (Sunset/communications)。
変更を破るためのRFCプロセス:ビジネスの正当化、移行計画、アーティファクト、日付。
Unified APIディレクトリ:図、バージョン、Sunsetカレンダー、連絡先が表示されます。
14)アンチパターン
「Quiet」ブレーク:バージョンなしでステータス/エラー/フィールドタイプを変更します。
protobuf番号の再利用-リプレイと古いクライアントを破壊します。
グラフQLフィールドテレメトリなし-タッチ除去。
グローバルv2トータル-ポイント進化の代わりにメガマイグレーション。
パブリックAPIのクエリパラメータのバージョンは、明らかではなく脆弱なスキームです。
移行ガイドや例はありません-パートナーのストール、締め切りは中断されます。
15)新しいバージョンのチェックリストリリース
- スキーマ(OpenAPI/Protobuf/SDL)、 linters、 breaking-checkを更新しました。
- 統合テストと契約テスト(CDC)を追加しました。
- SDK/サンプルコード/移行ガイドとChangelog対応。
- 廃止/日没有効(旧バージョン)+ページの移行方法。
- メトリクスを比較するカナリア/シャドウプラン、アラート、ダッシュボード。
- 後方互換性は合意された期間維持されます。
- ロールバック計画とリスクマトリックスは合意した。
概要
安定したAPIはプロセスであり、一度ではありません。"ルールに従って生きる:SemVer+add-only evolution+circuit register+contract tests+Sunset procedures。別のスタイル(REST/gRPC/GraphQL)とそのポリシー、ゲートウェイAPIへのルートバージョン、カナリアのロールアウト、エフェクトの測定。このようにして「、驚きを断ち切る」ことを避け、パートナーの統合を加速し、金銭的およびコンプライアンスに重要なドメインの予測可能性を維持します。