Versificación de API e interoperabilidad contractual
TL; DR
La compatibilidad es disciplina, no suerte. Mantenga una clara política de versiones (SemVer), matemática de cambios (que «rompe», que no), pruebas de contratos, registros de esquemas y procedimientos Sunset. Para el dinero y el compliance - riguroso NAT/gRPC con vN, para las agregaciones de UI - evolutivo GraphQL con '@ deprecated'. Siempre: tráfico canario, compatibilidad inversa ≥ un ciclo de lanzamiento, gaidas migratorias, telemetría de uso de campos.
1) Conceptos y objetivos básicos
Backwards-compatible (BC): los clientes antiguos se acercan al nuevo servidor.
Forwards-compatible (FC): nuevos clientes (limitados) se acercan al antiguo servidor.
Compatibilidad con cables: el formato en el «alambre» no se rompe (especialmente importante para gRPC/Protobuf).
SemVer: `MAJOR. MINOR. PATCH '- Rompe el contrato → aumenta MAJOR.
Objetivo: minimizar los cambios disruptivos y proporcionar ventanas de migración predecibles.
2) Matriz de cambios: lo que se puede y lo que no se puede
3) Políticas para diferentes estilos de API
3. 1 REST
Versión en URI ('/v1/... ') o en dominio (' api-v1. '). La versión de cabecera es sólo para casos internos.
Agregue, no elimine: los nuevos campos son aprox., antiguos. Marque «deprecated» en el diagrama y deje un mínimo de un ciclo.
Estados/errores: no cambie los códigos y la estructura de 'error. code/error. message/error. details`.
La idempotencia es inmutable: no convierta un 'POST' seguro con 'Idempotency-Key' en un desafío «conductualmente diferente».
3. 2 gRPC / Protobuf
Los números de campo son sagrados: no vuelva a usar los números eliminados, marque como 'reservado'.
Sólo la adición de nuevos campos optional/repite; «duro obligatorio» - a través de la validación, no 'required'.
Paquetes de versión: 'payments. v1`, `payments. v2`.
Compatibilidad de servicios: nuevos RPC → nuevo método; el comportamiento de los viejos no cambia.
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
Evolución sin v2: añadir campos/tipos; eliminación - a través de '@ deprecated (reason)' con el anuncio de la ventana.
Persisted Queries: para clientes públicos, use una lista blanca de solicitudes, más fácil de controlar la compatibilidad.
Campo-nivel authZ y telemetría: sepa qué campos se utilizan realmente antes de desinstalar.
graphql type Payout {
id: ID!
amountMinor: Long!
currency: String!
comment: String @deprecated(reason: "Use note")
note: String
}
3. 4 Webhooks
Versión en ruta ('/webhooks/v1/payments ') y sobre fijo del evento (' event _ id ',' type ',' ts', 'data').
Mantener las firmas/NMAS sin cambios; nuevos algoritmos - como una opción con una bandera.
Extensiones - sólo a través de los nuevos campos 'data.' y 'headers' - sin eliminar los antiguos.
4) API Gateway y enrutamiento de versiones
Rules-based routing: por prefijo '/v1 ', por encabezado' X-Api-Version ', por dominio.
Shadow/Canary: refleja parte del tráfico de producción a la nueva versión «en la sombra», compara las respuestas.
Rate/Quotas per-version: protege a los clientes antiguos durante la migración.
- 'Sunset:
' - fecha de apagado de la versión - 'Deprecation: true' - versión obsoleta
- `Link:
; rel = «deprecation» '- en migración changelog/hyde
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) Registros de esquemas y contratos
OpenAPI / JSON Schema для REST; Protobuf descriptors для gRPC; SDL registry для GraphQL.
CI-check: linters + «breaking-changes check» en PR.
Consumer-Driven Contracts (CDC): Pruebas de consumo (Nat/análogo) - Protección contra roturas imperceptibles.
Changelog: machine-readable (por ejemplo, 'CHANGELOG. md '+ notas de lanzamiento en el registro).
6) Evolución de los campos: reglas prácticas
ID/claves: no cambie el formato (UUID↔int) sin el nuevo campo '_ v2' y el período de transición.
Tiempo/moneda: mantenga UTC ISO-8601/epoch y amount_minor + currency; no cambie la escala (centavos/centavos).
Enum: agregue valores - aprox; no cambie el significado de los viejos. Para NAT - dar valores de cadena, no ints.
Paginación: cursor-based es más estable; no cambie la semántica del cursor.
7) Despricación y «Sunset» -procedura
1. Anuncio (T-90/60): changelog, mailing a partners, titulares de 'Deprecation/Sunset'.
2. Período de duplicación: V1 y V2 funcionan en paralelo; V1 está provisto de advertencias en las respuestas/logs.
3. Telemetría de uso: ¿quién más llama a V1? Contactos puntuales.
4. Congelación V1: Sólo bagfix/sin fich.
5. Apagado (Sunset): 410 Gone o página de flujo con una instrucción de migración.
8) Lanzamientos sin dolor: estrategias de colocación
Blue/Green o Weighted routing: 1-5-25-50-100% de tráfico.
Ventana de compatibilidad: mínimo de 1-2 lanzamientos menores, con más frecuencia de 6-12 meses para APIs externas.
Flags de características: para incluir nuevos campos/ramas de lógica sin cambiar de versión.
Leer/Escribir-dividir: primero agregue soporte para leer un nuevo campo, luego comience a escribirlo.
9) Pruebas de compatibilidad (paquete de prácticas)
Pruebas de oro para respuestas de versiones antiguas.
Pruebas de circuito diff: prohibición de breaking en CI.
Replay las pistas de producción en staging para V2 (shadow).
Back/Forward scripts: nuevo cliente en el servidor antiguo y viceversa (donde FC es válido).
Pruebas contractuales de webhooks: verificación de firma, formato, tiempo.
10) Métricas y SLO del proceso de versionamiento
% de clientes en el último MINOR (objetivo ≥ 80% antes de Sunset).
Errores de compatibilidad/inaccesibilidad en la versión (el objetivo es 0).
Porcentaje de llamadas de versión obsoleta (descendente a Sunset).
Tiempo de migración del cliente (mediana/p95).
Latency/regression delta entre versiones (no peor que la básica).
11) Ejemplos de artefactos
OpenAPI (fragmento, eliminación de campos):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 (paquete reservado y v2):
proto syntax = "proto3";
package payouts. v1;
message Payout { reserved 5; string id=1; int64 amount_minor=2; string currency=3; }
GraphQL (Despricación):
graphql type Query { payout(id: ID!): Payout }
12) Versificación de canales adyacentes
SDK/CLI: SemVer + dependencia de la versión API, la compatibilidad está estipulada en README.
Eventos/Streams (WS/Kafka): versión en 'envelope. version`; nuevos atributos - opcionales; el dedoup y los currículums funcionan de la misma manera entre versiones.
Informes/CSV: versión en nombre de archivo/casquillo; agregar columnas a la derecha; no cambie el orden/los tipos.
13) Gobierno y roles
Propietario del contrato (domain owner), API Steward (reglas y linters), Release Manager (Sunset/comunicaciones).
Proceso de RFC para cambios de breaking: justificación de negocios, plan de migración, artefactos, fechas.
Directorio único de API: donde los esquemas, versiones, calendario Sunset, contacto son visibles.
14) Anti-patrones
Roturas «silenciosas»: cambiamos el estado/error/tipo de campo sin versión.
Volver a usar los números protobuf: destruye los retablos y los viejos clientes.
GraphQL sin telemetría de uso de campos: elimina el «tacto».
El v2 global de todo es un megamigrado en lugar de una evolución puntual.
La versión en el parámetro query para la API pública es un esquema no visible y vulnerable.
No hay guidas migratorias y ejemplos: los socios se arrastran, los plazos se rompen.
15) Check-list del lanzamiento de la nueva versión
- Se ha actualizado el esquema (OpenAPI/Protobuf/SDL), se han completado los linters y los cheques de breaking.
- Se agregaron las pruebas de integración y contratación (CDC).
- SDK/código de ejemplo/hyde migratorio y Changelog están listos.
- Se incluye 'Deprecation/Sunset' (para la versión antigua) + página 'Cómo migrar'.
- Canary/Shadow plan, alertas y dashboards de comparación métrica.
- La compatibilidad inversa se ha mantenido durante el período acordado.
- Se acuerda un plan de retroceso (rollback) y una matriz de riesgo.
Resumen
Una API estable es un proceso, no «de una vez por todas». Vive según las reglas: SemVer + add-only evolución + registro de circuitos + pruebas contractuales + Sunset-procedimientos. Separe los estilos (NAT/gRPC/GraphQL) y sus políticas, enrute las versiones en la API Gateway, deslice los canarios, mida el efecto. Así que evitará «sorpresas rompedoras», acelere la integración de socios y mantenga la previsibilidad para dominios críticos de efectivo y cumplimiento.