Cómo versionar una API sin romper a los consumidores
- api
- versionado
- breaking changes
- endpoints
- desarrollo
- software
Cuando construyes una API, sabes que en algún momento necesitarás modificarla. El verdadero desafío no es cambiarla, sino hacerlo sin romper los sistemas de tus clientes o las aplicaciones internas que dependen de ella. Un buen versionado de API es la diferencia entre una evolución controlada y un problema constante para todos los involucrados. Mi experiencia con clientes me ha enseñado que es mejor pensar en esto desde el día uno, incluso en proyectos pequeños.
Por qué los breaking changes no son una opción
Un breaking change es cualquier modificación en tu API que exige que un consumidor cambie su código para seguir funcionando. Esto incluye eliminar un endpoint, cambiar el nombre de un campo o modificar el tipo de datos esperado en una respuesta. Para tus usuarios, estas rupturas se traducen en tiempo perdido depurando o, peor aún, en una interrupción del servicio que les cuesta dinero.
Cuando un cliente me llega con problemas de integraciones rotas, casi siempre se debe a un cambio de API que no se comunicó o gestionó bien. Evitar estos cambios disruptivos es el objetivo principal del versionado. Es una promesa de estabilidad que tu API debe ofrecer a sus usuarios.
Estrategias de versionado de API
Existen varias formas de implementar el versionado, cada una con sus ventajas y desventajas. La elección depende del contexto de tu proyecto, de la madurez de tu API y de la relación con tus consumidores. No hay una solución universalmente “mejor”, solo la más adecuada para tu caso.
Versionado por URI (Path versioning)
Esta es la forma más común y visible de versionar una API. Simplemente incluyes el número de versión directamente en la URL, como /api/v1/recursos o /api/v2/recursos. Es fácil de entender y de implementar tanto para el proveedor como para el consumidor.
// Ejemplo con Express.js
app.get('/api/v1/usuarios', (req, res) => { /* ... */ });
app.get('/api/v2/usuarios', (req, res) => { /* ... */ });
Versionado por Header
Aquí, la versión se especifica en las cabeceras HTTP de la solicitud, típicamente en la cabecera Accept. Por ejemplo, Accept: application/vnd.miapi.v1+json. Este método es menos intrusivo en la URL y permite que el mismo endpoint sirva diferentes versiones del recurso.
GET /api/usuarios HTTP/1.1
Host: api.ejemplo.com
Accept: application/vnd.miapi.v1+json
Versionado por Query Parameter
La versión se pasa como un parámetro en la cadena de consulta, como /api/recursos?version=1. Es sencillo de implementar rápidamente, pero a menudo se considera menos limpio que el versionado por URI o por cabecera para APIs RESTful. Puede llevar a problemas de cacheado si no se maneja correctamente.
Lo que ganas y lo que complicas con cada método
Mi regla es simple: elige la estrategia que tus consumidores entenderán más fácilmente y que tu equipo pueda mantener sin fricciones. No te compliques con soluciones exóticas si no hay una necesidad real que lo justifique.
| Estrategia | Lo que ganas | Lo que complicas |
|---|---|---|
URI (/vX/) | Claridad máxima, intuitivo, fácil cacheo. | URLs cambian, puede alargar el código cliente. |
Header (Accept:) | URLs consistentes, mayor flexibilidad. | Menos visible, implementación más compleja en algunos casos. |
Query Param (?v=X) | Facilidad de implementación para cambios rápidos. | Menos RESTful, posibles problemas de cacheo. |
Gestionar la deprecación y el fin de vida de las versiones
Lanzar una nueva versión no significa que la anterior deba desaparecer de inmediato. Es necesario dar un periodo de gracia a los consumidores. Mi enfoque es mantener las dos últimas versiones estables en producción: la versión N y la N-1.
Cuando se introduce una nueva versión (por ejemplo, v3), la más antigua (v1) se marca como “deprecated” y se anuncia su fecha de fin de soporte. Esto da tiempo suficiente a los consumidores para actualizar sus integraciones antes de que la versión antigua deje de funcionar. Una buena práctica es usar cabeceras HTTP como Deprecation y Link para comunicar el estado de una versión antigua y apuntar a la nueva. Además, se necesita una documentación clara sobre cómo usar tu proyecto y las políticas de versionado.
Si tienes que lidiar con problemas de rendimiento o seguridad en tus APIs, una implementación de rate limiting en tu API puede ser tan importante como el versionado para mantener la estabilidad del servicio.
Cuándo es un breaking change y cuándo no
La diferencia entre un cambio menor y un breaking change no es trivial. Un cambio menor puede ser añadir un nuevo campo opcional a la respuesta JSON, o un nuevo endpoint que no afecte a los existentes. Un breaking change es cualquier cosa que fuerce a un consumidor a cambiar su código para que su aplicación siga funcionando como antes.
Esta distinción es crítica para decidir si necesitas una nueva versión o si puedes lanzar un cambio sin afectar a nadie.
Lo que sí es un breaking change:
- Eliminar un campo existente en una respuesta.
- Cambiar el nombre de un campo.
- Modificar el tipo de datos de un campo (ej. de
stringainteger). - Cambiar el formato de la respuesta para un
endpointya existente. - Eliminar o renombrar un
endpoint. - Modificar la autenticación o los permisos de forma que afecte al acceso de los usuarios.
Lo que no es un breaking change:
- Añadir nuevos
endpoints. - Añadir campos opcionales a una respuesta existente.
- Modificar el orden de los campos en una respuesta (si el consumidor no depende de un orden específico).
- Cambiar la implementación interna sin modificar la interfaz pública de la API.
La comunicación con tus consumidores es clave, pero también lo es el rigor en tu propia definición de lo que es un breaking change. La transparencia genera confianza.
Si estás pensando en la arquitectura de tus servicios, esta discusión sobre cuándo dividir un proyecto en microservicios y cuándo no puede darte una perspectiva útil. Además, entender por qué tu código funciona en local y falla en producción es esencial para evitar sorpresas en tus APIs. Finalmente, una buena gestión de la caché en aplicaciones web puede complementar tu estrategia de versionado para mejorar el rendimiento.
Técnico freelance especializado en desarrollo a medida, automatizaciones con IA y gestión técnica para negocios en España. Más sobre mí →
¿Necesitas desarrollo a medida?
Desarrollo funcionalidades específicas, integraciones entre sistemas y herramientas internas. Si se puede programar, probablemente puedo hacerlo.