Versioning API et compatibilité contractuelle
TL; DR
L'interopérabilité est une discipline, pas une chance. Gardez une politique de version claire (BouVer), des mathématiques de changement (ce qui « casse », ce qui n'est pas le cas), des tests contractuels, des registres de schémas et des procédures Sunset. Pour l'argent et la complication - le strict REST/gRPC avec vN, pour les agrégations UI - le GraphQL évolutif avec « @ deprecated ». Toujours : le trafic de canari, la compatibilité inverse ≥ un релизный le cycle, migratoire гайды, телеметрия les utilisations des champs.
1) Concepts et objectifs de base
Backwards-compatible (BC) : les anciens clients conviennent au nouveau serveur.
Forwards-compatible (FC) : de nouveaux clients (limités) conviennent à l'ancien serveur.
Compatibilité sans fil : le format sur le « fil » ne se brise pas (particulièrement important pour gRPC/Protobuf).
SemVer: `MAJOR. MINOR. PATCH '- vous cassez le contrat → vous augmentez MAJOR.
Objectif : minimiser les changements cassants et fournir des fenêtres de migration prévisibles.
2) Matrice du changement : ce qui est possible et ce qui ne peut pas
3) Politiques pour différents styles d'API
3. 1 REST
Version dans l'URI ('/v1/... ') ou dans le domaine (' api-v1. '). La version en-tête est uniquement pour les cas internes.
Ajoutez, ne supprimez pas : les nouveaux champs sont ok, les anciens - marquez comme « deprecated » dans le schéma et laissez au moins un cycle.
Statuts/erreurs : ne changez pas les codes et la structure 'error. code/error. message/error. details`.
L'idempotence est inchangée : ne transformez pas un 'POST' sécurisé avec 'Idempotency-Key' en un défi « comportemental différent ».
3. 2 gRPC / Protobuf
Les numéros de champs sont sacrés : n'utilisez pas trop les numéros supprimés, marquez comme « réservé ».
Uniquement l'ajout de nouvelles options/répit de champs ; « rigide obligatoire » - par validation, non « required ».
Paquets de version : 'payments. v1`, `payments. v2`.
Interopérabilité des services : les nouveaux RPC → une nouvelle méthode ; on ne change pas le comportement des anciens.
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
Évolution sans v2 : ajouter des champs/types ; suppression - via '@ deprecated (reason)' avec l'annonce de la fenêtre.
Questions persistantes : pour les clients publics, utilisez la liste blanche des demandes - il est plus facile de contrôler la compatibilité.
Champ-level authZ et télémétrie : sachez quels champs sont réellement utilisés avant de les supprimer.
graphql type Payout {
id: ID!
amountMinor: Long!
currency: String!
comment: String @deprecated(reason: "Use note")
note: String
}
3. 4 Webhooks
Version dans le chemin ('/webhooks/v1/payments ') et enveloppe d'événement fixe (' event _ id ',' type ',' t', 'data').
Conserver les signatures/NMAS inchangées ; les nouveaux algorithmes sont comme une option avec un drapeau.
Extensions - uniquement via les nouveaux champs « data. » et « headers » - sans supprimer les anciens.
4) API Gateway et routage de version
Rules-based routing : par le préfixe '/v1 ', par l'en-tête' X-Api-Version ', par le domaine.
Shadow/Canary : Reflétez une partie du trafic de production sur la nouvelle version « dans l'ombre », comparez les réponses.
Rate/Quotas per-version : protège les anciens clients pendant la migration.
- 'Sunset :
'- date d'arrêt de la version - 'Deprecation : true '- la version est obsolète
- `Link:
; rel = « deprecation » '- sur changelog/hyde de 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) Registres des régimes et contrats
OpenAPI / JSON Schema для REST; Protobuf descriptors для gRPC; SDL registry для GraphQL.
Contrôles CI : linters + « breaking-changes check » sous PR.
Contrats de Consommation-Driven (CDC) : Tests de Consommation (Pact/Équivalent) - Protection contre les cassures non visibles.
Changelog : machine-readable (par exemple, 'CHANGELOG. md' + note de sortie dans le registre).
6) Évolution des champs : règles pratiques
ID/clés : ne changez pas le format (UUID↔int) sans le nouveau champ '_ v2' et la période de transition.
Temps/devise : tenez UTC ISO-8601/epoch et amount_minor + currency ; ne changez pas d'échelle (centimes/cents).
Enum : ajouter des valeurs - ok ; ne changez pas le sens des anciens. Pour REST, donnez des valeurs string et non ints.
Pagination : cursor-based est plus stable ; ne changez pas la sémantique du curseur.
7) Dépriscation et « Sunset » -prozedura
1. Annonce (T-90/60) : changelog, envoi aux partenaires, titres « Deprecation/Sunset ».
2. Période de duplication : V1 et V2 fonctionnent en parallèle ; V1 est muni d'alertes dans les réponses/logs.
3. Télémétrie d'utilisation : Qui d'autre appelle V1 ? contacts ponctuels.
4. Gel V1 : uniquement bagfix/sans fiche.
5. Désactivation (Sunset) : 410 Gone ou une page de bloc avec une instruction de migration.
8) Releases sans douleur : stratégies de mise en place
Routage Bleu/Vert ou Weighted : 1-5-25-50-100 % du trafic.
Fenêtre de compatibilité : minimum 1-2 versions mineures, plus de 6-12 mois pour les API externes.
Feature Flags : pour inclure de nouveaux champs/branches de logique sans changer de version.
Read/Write-clivage : ajoutez d'abord le support de lecture du nouveau champ, puis commencez à l'écrire.
9) Test de compatibilité (pack de pratique)
Tests Golden sur les réponses des anciennes versions.
Diff tests de circuits : interdiction de breaking en CI.
Replay des pistes de production sur staging pour V2 (shadow).
Scripts Back/Forward : nouveau client sur l'ancien serveur et vice versa (là où FC est autorisé).
Tests contractuels de webhooks : vérification de la signature, du format, de l'heure.
10) Métriques et SLO du processus de versioning
% des clients de la dernière MINOR (objectif ≥ 80 % avant Sunset).
Erreur de compatibilité/indisponibilité de sortie (cible 0).
Proportion d'appels de version obsolète (décroissant vers Sunset).
Temps de migration du client (médian/p95).
Latitude/région delta entre les versions (pas pire que la version de base).
11) Exemples d'artefacts
OpenAPI (fragment, privation de champ) :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 (paquet réservé et v2) :
proto syntax = "proto3";
package payouts. v1;
message Payout { reserved 5; string id=1; int64 amount_minor=2; string currency=3; }
GraphQL (privation) :
graphql type Query { payout(id: ID!): Payout }
12) Versionage des canaux adjacents
SDK/CLI : BouVer + dépendance à la version API, compatibilité stipulée dans README.
Événements/strims (WS/Kafka) : version dans 'envelope. version`; les nouveaux attributs sont facultatifs ; dedup et m fonctionnent de la même manière entre les versions.
Reporting/CSV : version dans le nom de fichier/chapeau ; ajouter des colonnes à droite ; ne changez pas l'ordre/les types.
13) Gouvernance et rôles
Propriétaire du contrat (domain owner), API Steward (règles et linters), Release Manager (Sunset/communications).
Processus RFC pour le breaking-change : analyse de rentabilisation, plan de migration, artefacts, dates.
Répertoire API unique : où les schémas, les versions, le calendrier Sunset, le contact sont visibles.
14) Anti-modèles
Rupture « silencieuse » : nous changeons le statut/erreur/type du champ sans version.
La réutilisation des numéros protobuf détruit les relais et les anciens clients.
GraphQL sans télémétrie d'utilisation des champs - suppression du « toucher ».
Le v2 mondial est un méga-jeu au lieu d'une évolution ponctuelle.
La version dans le paramètre query pour l'API publique n'est pas un schéma évident et vulnérable.
Il n'y a pas d'hydes migratoires et d'exemples - les partenaires remorquent, les délais échouent.
15) Check-list de la nouvelle version
- Le schéma (OpenAPI/Protobuf/SDL) a été mis à jour, les linters et les breaking-checks ont été passés.
- Les tests d'intégration et contractuels (CDC) ont été ajoutés.
- SDK/exemple de code/hyde de migration et Changelog sont prêts.
- Inclus 'Deprection/Sunset' (pour l'ancienne version) + page « How to migrate ».
- Plan Canary/Shadow, alertes et dashboards comparatifs de métriques.
- La rétrocompatibilité a été maintenue pour une durée convenue.
- Le plan de reprise (rollback) et la matrice des risques sont harmonisés.
Résumé
L'API stable est un processus, pas « une fois pour toutes ». Vivez selon les règles : BouVer + évolution supplémentaire + registre des schémas + tests contractuels + procédures Sunset. Séparez les styles (REST/gRPC/GraphQL) et leurs stratégies, acheminez les versions vers l'API Gateway, roulez avec des canaries, mesurez l'effet. De cette façon, vous éviterez les « surprises cassantes », accélérerez l'intégration des partenaires et conserverez la prévisibilité pour les domaines monétaires et de conformité critiques.