Contrats et gateway¶
Définir les interfaces avant l'implémentation, gouverner le trafic au point d'entree — le socle de toute communication inter-services fiable.
API gateway¶
L'API gateway est le point d'entree unique vers vos services backend. Il prend en charge les preoccupations transversales pour que vos services n'aient pas à le faire.
graph TD
Web[Client Web]
Mobile[Client Mobile]
Third[API Tierce]
GW[API Gateway<br/>auth - rate limit - routing - TLS]
SvcA[Service Orders]
SvcB[Service Users]
SvcC[Service Inventory]
Web --> GW
Mobile --> GW
Third --> GW
GW -->|"route /orders"| SvcA
GW -->|"route /users"| SvcB
GW -->|"route /inventory"| SvcC Responsabilités du gateway¶
- Routage : diriger chaque requête vers le bon service selon l'URL, le header ou le sous-domaine
- Authentification et autorisation : valider le token JWT ou la clé API avant de transmettre
- Rate limiting : limiter les appels par client pour protéger les services backend
- TLS termination : gérer HTTPS au niveau du gateway, communication interne en HTTP simple
- Agrégation : composer plusieurs appels backend en une seule réponse (BFF pattern)
- Logging et tracing : injecter les correlation IDs, centraliser les logs d'accès
BFF (Backend for Frontend)¶
Le BFF est un gateway specialise par type de client. Le client mobile a besoin de payloads légers et d'un seul appel pour afficher un écran. Le client web desktop peut tolérer des payloads plus riches. Le BFF compose les appels backend et formate la réponse selon les besoins du client.
graph TD
Mobile[Client Mobile] --> BFF_M[BFF Mobile]
Web[Client Web] --> BFF_W[BFF Web]
Admin[Client Admin] --> BFF_A[BFF Admin]
BFF_M --> SvcA[Service Orders]
BFF_M --> SvcB[Service Users]
BFF_W --> SvcA
BFF_W --> SvcB
BFF_W --> SvcC[Service Analytics]
BFF_A --> SvcA
BFF_A --> SvcC Règle : un BFF par expérience utilisateur, pas par plateforme technique. Si le mobile et le web affichent les mêmes écrans, un seul BFF suffit.
Outils¶
| Outil | Type | Forces |
|---|---|---|
| Kong | Gateway open source | Plugins riches, Lua/Go extensible |
| NGINX / Envoy | Reverse proxy | Performance brute, configuration declarative |
| AWS API Gateway | Managed | Intégration Lambda, pas d'infra a gérer |
| Traefik | Cloud-native | Auto-discovery (Docker, K8s), Let's Encrypt |
| Apigee | Enterprise | Governance, monetisation, analytics |
Pas de logique métier dans le gateway
L'API gateway ne doit pas contenir de logique métier. Si vous commencez a y écrire des transformations complexes, c'est un signe que la decomposition des services est mauvaise.
Service mesh¶
Le service mesh déplacé la gestion de la communication inter-services hors du code applicatif, dans des proxies sidecar déployés aux cotes de chaque service.
graph LR
subgraph "Service A"
AppA[App A]
SA[Sidecar proxy]
end
subgraph "Service B"
AppB[App B]
SB[Sidecar proxy]
end
CP[Control Plane<br/>Istio / Linkerd]
SA <-->|"mTLS"| SB
CP -.->|"config: retry, circuit break"| SA
CP -.->|"config: retry, circuit break"| SB
AppA <--> SA
AppB <--> SB Ce que le mesh apporte sans modifier le code applicatif :
- mTLS automatique : chiffrement et authentification mutuelle entre tous les services
- Retries et timeouts : configures au niveau du proxy, pas dans le code
- Circuit breaking : coupe le trafic vers un service defaillant
- Load balancing : répartition fine (round-robin, least-connections, canary)
- Tracing distribué : propagation automatique des headers de trace
- Métriques : latence, taux d'erreur, throughput sans instrumentation applicative
Quand c'est justifie vs overkill¶
| Justifie | Overkill |
|---|---|
| Plus de 10 services avec flux inter-services | Moins de 5 services |
| Besoin de mTLS partout | Équipe ops petite ou sans expérience du mesh |
| Équipe ops capable de maintenir le control plane | Besoins couverts par les librairies applicatives |
| Observabilité fine requise au niveau réseau | Environnement simple sans contrainte zero-trust |
Coût opérationnel réel
Un service mesh ajoute de la latence (sidecar proxy), de la complexité opérationnelle et des ressources. Ne l'introduisez que si vous avez un besoin concret qu'il résout.
Contrats d'API¶
Définir le contrat avant l'implémentation (contract-first) permet aux équipes de travailler en parallèle et evite les desaccords d'interpretation.
Contract-first vs code-first¶
Contract-first : on écrit la spec (OpenAPI, proto, AsyncAPI), on la fait valider par les consommateurs, puis on généré ou implémenté le code.
- Les équipes consumer et producer travaillent en parallèle
- La spec est la source de vérité
- Les breaking changes sont détectées avant le merge
Code-first : on écrit le code et on généré la spec depuis les annotations.
- Rapide a démarrer, spec synchronisée avec le code
- La spec reflete l'implémentation plutôt que le besoin du consommateur
- Moins adapté aux APIs publiques
Recommandation : contract-first pour les APIs exposees a des équipes externes ou des clients tiers. Code-first acceptable pour les APIs internes a une même équipe quand la velocite prime.
Formats de contrat¶
| Format | Protocole | Forces |
|---|---|---|
| OpenAPI 3.x | REST | Documentation auto, code génération, écosystème |
| Protobuf | gRPC | Typage fort, performance, backward compatibility |
| AsyncAPI | Messaging | Documentation des événements, code génération |
| GraphQL SDL | GraphQL | Schéma type, introspection, fédération |
Consumer-driven contracts (Pact)¶
Le problème classique : le producer change son API et casse les consumers sans le savoir. Les tests d'intégration de bout en bout sont lents et fragiles. Les consumer-driven contracts inversent la responsabilité.
sequenceDiagram
participant C as Consumer
participant PB as Pact Broker
participant P as Producer
C->>PB: 1. publie ses attentes (pact file)
Note over C: "je m'attends a GET /users/1<br/>retourne {id, name, email}"
P->>PB: 2. recupere les pacts
P->>P: 3. verifie que son API satisfait les pacts
P-->>PB: 4. publie le resultat de verification
PB-->>C: 5. le consumer sait si le deploy est safe Le flux Pact :
- Le consumer écrit un test qui décrit ce qu'il attend du producer (requête + réponse minimale)
- Ce test généré un fichier pact (JSON) publie sur le Pact Broker
- Le producer récupéré les pacts et les rejoue contre son API
- Si tous les pacts passent, le producer peut déployer sans casser ses consumers
Avantage clé : le consumer ne teste que ce qu'il utilisé. Si le producer ajoute un champ, aucun pact ne casse. Si le producer supprimé un champ utilisé, le pact échoué avant le merge.
{
"consumer": { "name": "OrderUI" },
"provider": { "name": "UserService" },
"interactions": [
{
"description": "get user by id",
"request": {
"method": "GET",
"path": "/users/usr-001"
},
"response": {
"status": 200,
"body": {
"id": "usr-001",
"name": "Alice Martin",
"email": "alice@example.com"
}
}
}
]
}
API versioning¶
Les APIs evoluent. Les consumers existants ne doivent pas casser à chaque changement. La stratégie de versioning définit comment cohabitent les anciennes et nouvelles versions.
Stratégies de versioning¶
| Stratégie | Exemple | Avantage | Inconvénient |
|---|---|---|---|
| URL path | /v1/orders, /v2/orders | Explicite, facile à router | Duplication de routes |
| Header | Accept: application/vnd.api.v2 | URL propre | Moins visible, debug difficile |
| Query parameter | /orders?version=2 | Simple a implémenter | Pollue l'URL, cache complique |
| Content negociation | Accept: application/json;v=2 | Standard HTTP | Support client inegal |
Recommandation : URL path pour les APIs publiques (clarte, routage simple, documentation evidente). Header pour les APIs internes quand la gouvernance est mature.
Breaking vs non-breaking changes¶
| Non-breaking (safe) | Breaking (casse les consumers) |
|---|---|
| Ajouter un champ optionnel | Supprimer un champ |
| Ajouter un endpoint | Renommer un champ |
| Ajouter une valeur d'enum | Changer le type d'un champ |
| Relacher une validation | Rendre obligatoire un champ optionnel |
| Ajouter un header optionnel | Changer un code de retour |
Deprecation policy¶
Ne jamais supprimer une version sans prévenir. Un cycle de deprecation standard :
- Announce : documenter la deprecation (header
Deprecation, changelog, email) - Sunset header :
Sunset: Sat, 01 Nov 2025 00:00:00 GMT— date de fin de support - Monitoring : mesurer le trafic sur la version deprecee pour identifier les consumers restants
- Grâce period : maintenir la version au minimum 6 mois après l'annonce (12 mois pour les APIs publiques)
- Shutdown : retourner
410 Goneavec un lien vers la nouvelle version
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 01 Nov 2025 00:00:00 GMT
Link: </v3/orders>; rel="successor-version"
Évolution avec Protobuf¶
Protobuf offre la meilleure compatibilité ascendante et descendante parmi les formats :
- Les champs sont identifiés par numéro, pas par nom
- Ajouter un champ = nouveau numéro, les anciens clients ignorent le champ inconnu
- Supprimer un champ = marquer le numéro
reserved - Les clients anciens et nouveaux coexistent naturellement
message Order {
string id = 1;
string customer_id = 2;
OrderStatus status = 3;
// champ supprime : ne jamais reutiliser le numero 4
reserved 4;
// nouveau champ : les anciens clients l'ignorent
string tracking_url = 5;
}
Versionner les événements aussi
Les événements asynchrones (Kafka, RabbitMQ) doivent être versionnes avec la même rigueur que les APIs REST. Un événement OrderCreated_v1 et OrderCreated_v2 peuvent coexister sur le même topic. Le consumer géré les deux versions ou migré. AsyncAPI formalise ces contrats.
Gouvernance des APIs¶
Sans gouvernance, les APIs proliferent avec des conventions différentes, des versions non documentees et des contracts implicites.
Catalogue d'APIs¶
Un registre centralise de toutes les APIs du système. Chaque API est documentee avec :
- Sa spec (OpenAPI, proto, AsyncAPI)
- Son propriétaire (équipe responsable)
- Son statut (active, deprecated, sunset)
- Ses consumers connus
- Ses SLOs (latence, disponibilité, throughput)
Outils : Backstage (Spotify), SwaggerHub, Apicurio, Postman.
Linting automatique¶
Valider automatiquement les specs dans la CI pour imposer les conventions :
- Nommage cohérent (camelCase vs snake_case)
- Codes de retour corrects (201 pour création, 404 pour not found)
- Pagination obligatoire pour les listes
- Champs de date au format ISO 8601
- Réponses d'erreur standardisees (RFC 7807 Problem Détails)
Spectral (Stoplight) permet de définir des règles de linting pour OpenAPI et AsyncAPI.
# .spectral.yaml
rules:
operation-operationId:
severity: error
oas3-valid-media-example:
severity: warn
path-keys-no-trailing-slash:
severity: error
La gouvernance comme enabler
La gouvernance des APIs ne doit pas ralentir les équipes. Automatiser le linting dans la CI, publier automatiquement dans le catalogue, et limiter la revue manuelle aux breaking changes. L'objectif est la cohérence sans le goulot d'étranglement.
Chapitre suivant : Sagas et integration — transactions distribuées, compensations et patterns de fiabilité.