Versionização da API e compatibilidade contratual
TL; DR
Compatibilidade é disciplina, não sorte. Mantenha uma política clara de versões (SemVer), matemática de mudanças (o que «quebra» que não), testes contratuais, registros de circuitos e procedimentos sunset. Para dinheiro e complacência - rigoroso com , para agregações UI - evolucionário com '@ deprecated'. Sempre: tráfego canário, compatibilidade inversa ≥ um ciclo de lançamento, guindastes migratórios, telemetria de uso de campos.
1) Conceitos básicos e objetivos
Backwards-compatível (BC): O novo servidor é adequado a clientes antigos.
Forwards-compatível (FC): Novos clientes (restritos) se adequam ao servidor antigo.
Compatibilidade Wire: O formato no fio não é quebrado (especialmente importante para o gRPC/Protobuf).
SemVer: `MAJOR. MINOR. PATCH '- Quebra o contrato → aumenta o MAJOR.
O objetivo é minimizar as mudanças de quebra e garantir janelas previsíveis de migração.
2) Matriz de alterações: o que pode ou não ser
3) Políticas para diferentes estilos de API
3. 1 REST
Versão em URI ('/v1/... ') ou domínio (' api-v1 '). A versão de título é apenas para casos internos.
Adicione, não remova: novos campos - ok, antigos - assinale como 'deprecated' no esquema e deixe pelo menos um ciclo.
Estado/erro: não altere os códigos e a estrutura do 'erro. code/error. message/error. details`.
Idempotidade é imutável: não transforme o seguro 'POST' s Idempotency-Key em um desafio «comportamentalmente diferente».
3. 2 gRPC / Protobuf
Os números de campo são sagrados: não use os números remotos, assinale como 'reserved'.
Apenas adicionar novos campos optional/repique; «rígidos obrigatórios» - através da validação, não «required».
Pacotes de versões: 'payments. v1`, `payments. v2`.
Compatibilidade de serviços: novos RPC → novo método; Não mudamos o comportamento dos velhos.
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
Evolução sem v2: adicione campos/tipos; remoção através de '@ deprecated (reason)' com o anúncio da janela.
Persisted Qualies: Para clientes públicos, use uma lista branca de solicitações - é mais fácil controlar a compatibilidade.
Field-level authZ e telemetria: saiba quais campos são realmente usados antes de ser removido.
graphql type Payout {
id: ID!
amountMinor: Long!
currency: String!
comment: String @deprecated(reason: "Use note")
note: String
}
3. 4 Webhooks
Versão no caminho ('/webhooks/v1/payments ') e envelope fixo do evento (' event _ id ',' tipo ',' ts ',' data ').
Assinaturas/NMAS mantêm inalteradas; novos algoritmos como opção de bandeira.
Extensões - somente através de novos campos 'data' e 'headers' - sem remover antigos.
4) API Gateway e rotinagem de versões
Rales-based roting: por prefixo '/v1 ', por título' X-Api-Versão ', por domínio.
Shadow/Canary: Reflita parte do tráfego de produção em uma nova versão de «sombra», compare as respostas.
Rate/Cotas por-versão: protege clientes antigos durante a migração.
- 'Sunset:
' - Data de desativação da versão - 'Deprecation: true' - versão obsoleta
- `Link:
; rel = «deprecation» '- para changelog/hyde migração
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 e contratos
OpenAPI / JSON Schema для REST; Protobuf descriptors для gRPC; SDL registry для GraphQL.
Verificações CI: linters + «breaking-changes check» em PR.
CDC (Consumer-Driven Contracts): Testes de consumo (Pact/equivalente) - Proteção contra quebras discretas.
Changelog: machine-readable (por exemplo, 'CHANGELOG. md' + notas de lançamento no registro).
6) Evolução dos campos: regras práticas
ID/chaves: não mude o formato (UUID↔int) sem o novo campo «_ v2» e o período de transição.
Tempo/moeda: mantenha UTC ISO-8601/epoch e amount _ menor + currency; Não mude de escala (centavos/centavos).
Enum: adicione os valores - ok; Não mudem o sentido dos velhos. Para REST - dê valores de string, não de ints.
Paginação: cursor-based mais estável; não altere a semântica do cursor.
7) Despricagem e «Sunset» -
1. Anúncio (T-90/60): changelog, e-mail para os parceiros, títulos de «Deprecation/Sunset».
2. Período de duplicação: V1 e V2 funcionam em paralelo; O V1 está equipado com avisos em respostas/logs.
3. Telemetria de uso: Quem mais chama V1? Contatos pontuais.
4. Congelamento V1: apenas bagfixs/sem fichas.
5. Desligamento (Sunset): 410 Gone ou página de bloco com instrução de migração.
8) Lançamentos sem dor: estratégias de pontuação
Blue/Green ou Weighted routing: 1-5-25-50-100% do tráfego.
Compatibility window: mínimo de 1 a 2 lançamentos menores, mais de 6 a 12 meses para APIs externas.
Função Flags: para incluir novos campos/ramais de lógica sem alterar a versão.
Read/Write-fragmentação: Primeiro adicione o suporte de leitura do novo campo e comece a escrevê-lo.
9) Testes de compatibilidade (pacote de práticas)
Testes de resposta de versões antigas.
Testes de diagramação divida: banimento de breaking em CI.
Replay caminhos de produção em staging para V2 (shadow).
Cenário Back/Forward: um novo cliente em um servidor antigo e vice-versa (onde o FC é permitido).
Testes contratuais de webhooks: verificação de assinatura, formato, hora.
10) Métricas e SLO do processo de versionização
% dos clientes no último MENOR (meta ≥ 80% para Sunset).
Erros de compatibilidade/indisponibilidade (alvo 0).
Proporção de chamadas antiquadas (decrescente para Sunset).
Tempo de migração do cliente (mediana/p95).
Latency/regressão delta entre versões (igual ao básico).
11) Exemplos de artefatos
OpenAPI (fatia, despercussão do campo):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 (reservado e v2 pacote):
proto syntax = "proto3";
package payouts. v1;
message Payout { reserved 5; string id=1; int64 amount_minor=2; string currency=3; }
GraphQL (despricagem):
graphql type Query { payout(id: ID!): Payout }
12) Versionização de canais adjacentes
SDK/CLI: SemVer + dependência da API, compatibilidade definida no README.
Eventos/striptease (WS/Kafka): versão em 'envelope. version`; novos atributos - opcionais; Dedups e m funcionam da mesma forma entre as versões.
Relatórios/CSV: versão em nome de arquivo/chapéu; Adicione colunas à direita; não altere a ordem/tipos.
13) Governance e papéis
Proprietário de contrato (domain owner), API Steward (regras e linteres), Release Gerente (Sunset/comunicações).
Processo RFC para mudanças de breaking: justificativa de negócios, plano de migração, artefatos, datas.
Um único diretório de API: onde os circuitos, versões, calendário sunset, contato são visíveis.
14) Anti-pattern
Quebra silenciosa: Altere status/erro/tipo de campo sem versão.
Reutilizar números protobuf - destrói réplicas e clientes antigos.
GraphQL sem telemetria de uso de campos - remover «toque».
V2 global é uma megamigação em vez de evolução pontual.
A versão em query-parâmetro para API pública é um padrão pouco claro e vulnerável.
Não há números de migração ou exemplos - os parceiros estão a rebocar, os prazos estão a perder.
15) Check-list de lançamento da nova versão
- O esquema (OpenAPI/Protobuf/SDL) foi atualizado e os links e breaking-check foram ultrapassados.
- Os testes de integração e contrato (CDC) foram adicionados.
- Pronto SDK/exemplo de código/hide migratório e Changelog.
- Incluídos 'Deprecation/Sunset' (para versão antiga) + página 'How to migrate'.
- Canary/Shadow plano, alertas e dashboards de comparação de métricas.
- Compatibilidade invertida guardada por tempo acordado.
- Plano de reversão (rollback) e matriz de risco estão alinhados.
Currículo
Uma API estável é um processo, não «de uma vez por todas». Viva de acordo com as regras: SemVer + add-only evolução + minúsculas de esquema + testes contratuais + procedimentos sunset. Divida os estilos (REST/gRPC/GraphQL) e as suas políticas, roda as versões para a API Gateway, deslize os canários e mede o efeito. Assim, você evita «surpresas quebrantes», acelere a integração dos parceiros e mantenha a previsibilidade para os domínios criteriosos em dinheiro e em dinheiro.