API versioning: estratégias para evoluir contratos sem quebrar clientes
1. Fundamentos do Versionamento de APIs
O versionamento de APIs é uma prática essencial para qualquer serviço que pretenda evoluir sem comprometer a experiência dos consumidores. O dilema central é: como adicionar novas funcionalidades, corrigir bugs ou alterar comportamentos sem quebrar integrações existentes?
Mudanças em APIs podem ser classificadas em dois grandes grupos:
- Breaking changes: alterações que quebram clientes existentes (remoção de campos, mudança de tipos, alteração de endpoints)
- Non-breaking changes: adições que não afetam consumidores atuais (novos campos opcionais, novos endpoints, novos métodos HTTP)
A semântica do versionamento semântico (semver) aplicada a APIs sugere que versões MAJOR indicam mudanças incompatíveis, MINOR indicam adições compatíveis e PATCH indicam correções compatíveis.
As consequências de não versionar são graves: clientes quebrados, retrabalho emergencial, perda de confiança dos integradores e danos à reputação do serviço.
2. Estratégias de Versionamento na URL (Path Versioning)
A abordagem mais simples e amplamente adotada é incluir a versão no caminho da URL:
GET /v1/usuarios
GET /v2/usuarios
POST /v1/pedidos
Vantagens:
- Simplicidade de implementação e descoberta explícita
- Fácil cache em CDNs e proxies
- Clareza para clientes sobre qual versão estão consumindo
Desvantagens:
- Poluição de URLs e duplicação de código no backend
- Rigidez em evoluções incrementais (cada mudança exige nova versão)
- Dificuldade em manter múltiplas versões simultâneas
Exemplo prático de resposta diferenciada entre versões:
Request:
GET /v1/usuarios/123
Response (v1):
{
"id": 123,
"nome": "Maria Silva",
"email": "maria@exemplo.com"
}
Request:
GET /v2/usuarios/123
Response (v2):
{
"id": 123,
"nome_completo": "Maria Silva",
"email": "maria@exemplo.com",
"telefone": "(11) 99999-8888"
}
3. Versionamento via Cabeçalhos HTTP (Header Versioning)
Nesta estratégia, a versão é especificada através de cabeçalhos HTTP, mantendo as URLs limpas:
GET /usuarios/123
X-API-Version: 1
GET /usuarios/123
Accept: application/vnd.minhaapi.v2+json
Prós:
- URLs limpas e consistentes
- Separação de preocupações (a versão é um meta-dado)
- Adequado para APIs RESTful puristas
Contras:
- Descoberta oculta (clientes precisam saber qual cabeçalho usar)
- Complexidade em documentação e testes
- Dificuldade em cachear respostas (cabeçalhos variam)
4. Versionamento por Parâmetro de Query
Uma abordagem simples que utiliza parâmetros na query string:
GET /usuarios?version=1
GET /usuarios?version=2
Casos de uso: APIs públicas com versionamento opcional, migrações graduais.
Limitações:
- Cache agressivo em CDNs (parâmetros podem ser ignorados)
- Ambiguidade em parâmetros (conflito com parâmetros de negócio)
- Difícil versionamento de recursos aninhados
5. Evolução Sem Quebra com Estratégias Não-Quebradoras
O ideal é evitar versionamento sempre que possível, adotando práticas que permitam evolução sem quebra:
Princípio de tolerância:
- Campos opcionais com defaults seguros
- Extensões via campos adicionais em objetos
- Uso de _links e HATEOAS para orientar clientes
Técnicas de depreciação:
- Cabeçalho Sunset: informa quando uma versão será descontinuada
- Cabeçalho Deprecation: avisa que o recurso está obsoleto
- Logs de aviso no corpo da resposta
Exemplo de resposta com depreciação:
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 31 Dec 2024 23:59:59 GMT
Content-Type: application/json
{
"id": 123,
"nome": "Maria Silva",
"_links": {
"self": "/v2/usuarios/123",
"migrate": "/docs/migration-v1-to-v2"
}
}
6. Estratégias de Transição e Suporte Múltiplo
Gerenciar o ciclo de vida das versões é crucial:
Ciclo de vida:
1. Lançamento: nova versão disponível
2. Convivência: múltiplas versões ativas simultaneamente
3. Depreciação: aviso de descontinuação
4. Descontinuação: remoção da versão antiga
Roteamento inteligente:
- Proxies reversos (Nginx, Envoy)
- Gateways de API (Kong, AWS API Gateway, Apigee)
Políticas de suporte:
- Janela de tempo mínima (ex: 6 meses de suporte simultâneo)
- Comunicação clara via changelogs e documentação
- Notificações proativas para clientes impactados
7. Versionamento em APIs GraphQL e gRPC
GraphQL: o versionamento é feito através de depreciação de campos e aliases:
type Usuario {
id: ID!
nome: String
nomeCompleto: String @deprecated(reason: "Use 'nome'")
email: String
}
gRPC: utiliza protobuf com números de campo imutáveis:
message Usuario {
int32 id = 1;
string nome = 2;
string email = 3;
string telefone = 4; // campo adicionado sem quebrar versão anterior
}
Design evolutivo: ambas as tecnologias incentivam tolerância a campos desconhecidos, reduzindo a necessidade de versionamento tradicional.
8. Boas Práticas e Checklist para Decisão
Documentação obrigatória:
- Changelog por versão detalhando mudanças
- Exemplos de migração entre versões
- Guias de depreciação
Testes de compatibilidade:
- Contratos OpenAPI/Swagger versionados
- Testes de regressão automatizados
- Testes de integração com clientes reais
Checklist final para escolha da estratégia:
| Critério | URL | Header | Query | Evolução |
|---|---|---|---|---|
| Simplicidade | ✅ | ❌ | ✅ | ❌ |
| Descoberta explícita | ✅ | ❌ | ❌ | ❌ |
| Cache eficiente | ✅ | ❌ | ❌ | ✅ |
| URLs limpas | ❌ | ✅ | ❌ | ✅ |
| Evolução incremental | ❌ | ✅ | ❌ | ✅ |
Decisão baseada em:
- Maturidade da API (pública vs interna)
- Perfil dos clientes (mobile, web, IoT)
- Frequência de mudanças (alta vs baixa)
Para APIs públicas com muitos consumidores, recomenda-se versionamento por URL combinado com estratégias de evolução não-quebradoras. Para APIs internas ou com poucos consumidores controlados, header versioning ou evolução sem versionamento são mais adequados.
Referências
- Microsoft REST API Guidelines - Versioning — Diretrizes oficiais da Microsoft para versionamento de APIs REST, incluindo estratégias de URL e cabeçalhos
- Google API Design Guide - Versioning — Documentação do Google sobre como versionar APIs, com foco em compatibilidade e evolução
- Stripe API Changelog and Versioning — Exemplo prático de como o Stripe gerencia versionamento com depreciação gradual e changelogs detalhados
- Semantic Versioning 2.0.0 — Especificação oficial do versionamento semântico, base para entender breaking vs non-breaking changes
- OpenAPI Specification - Versioning — Documentação oficial da OpenAPI sobre como versionar contratos de API com Swagger
- Nginx API Gateway and Version Routing — Guia da Nginx para roteamento inteligente de versões de API usando proxy reverso
- GraphQL Best Practices - Versioning — Abordagem do GraphQL para evolução de schema sem versionamento tradicional