Regla
Evita romper los contratos de la API pública.
Los cambios en los endpoints de la API pública que puedan romper
las solicitudes de los clientes existentes son cambios rupturistas (breaking changes).
Considera el contrato de la API como una promesa;
cambiarla después de que los clientes dependan deella romperá su código.
Lenguajes compatibles: PHP, Java, C#, Python, JavaScript, TypeScriptIntroducción
Las API públicas son contratos entre su servicio y sus consumidores. Una vez que los clientes dependen del formato de solicitud, la estructura de respuesta o el comportamiento de un endpoint, cambiarlo rompe su código. Los cambios disruptivos obligan a todos los clientes a actualizarse simultáneamente, lo cual a menudo es imposible cuando no se controlan los clientes. Las aplicaciones móviles no pueden ser actualizadas forzosamente, las integraciones de terceros necesitan tiempo de migración y los sistemas heredados pueden no actualizarse nunca.
Por qué es importante
Interrupción del cliente y confianza: Los cambios de API que rompen la compatibilidad causan fallos inmediatos en las aplicaciones cliente en producción. Los usuarios experimentan errores, pérdida de datos o interrupciones completas del servicio. Esto daña la confianza entre proveedores y consumidores de API, y viola el contrato implícito de que las API estables permanecen estables.
Costes de coordinación: Coordinar cambios disruptivos entre múltiples equipos de clientes es costoso y lento. Cada equipo necesita tiempo para actualizar el código, probar los cambios y desplegar. Para APIs públicas con clientes desconocidos (aplicaciones móviles, integraciones de terceros), la coordinación es imposible.
Proliferación de versiones: Los cambios disruptivos mal gestionados llevan a mantener múltiples versiones de API simultáneamente. Cada versión requiere rutas de código, pruebas, documentación y correcciones de errores separadas, multiplicando exponencialmente la carga de mantenimiento.
Ejemplos de código
❌ No conforme:
// Version 1: Original API
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json({ id: user.id, name: user.name });
});
// Version 2: Breaking change - renamed field
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json({
id: user.id,
fullName: user.name // Breaking: 'name' renamed to 'fullName'
});
});
Por qué está mal: Renombrar 'name' a 'fullName' rompe todos los clientes existentes que esperan el campo 'name'. El código del cliente que acceda a response.name recibirá 'undefined', causando errores. Este cambio obliga a todos los clientes a actualizarse simultáneamente o fallar.
✅ Conforme:
// Version 2: Additive change - keeps old field, adds new
app.get('/api/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json({
id: user.id,
name: user.name, // Keep for backward compatibility
fullName: user.name // Add new field (deprecated 'name')
});
});
// Or use API versioning
app.get('/api/v2/users/:id', async (req, res) => {
const user = await db.users.findById(req.params.id);
res.json({ id: user.id, fullName: user.name });
});
¿Por qué esto importa? Manteniendo lo antiguo nombre el campo mantiene la compatibilidad con versiones anteriores mientras añade nombre completo para nuevos clientes. Alternativamente, creando un nuevo endpoint versionado (/api/v2/) permite cambios disruptivos sin afectar a los clientes existentes que aún utilizan /api/v1/.
Conclusión
Evolucione las APIs mediante cambios aditivos: añada nuevos campos, nuevos endpoints, añada parámetros opcionales. Cuando los cambios disruptivos sean inevitables, utilice el versionado de API para ejecutar versiones antiguas y nuevas de forma concurrente. Depreque campos antiguos con plazos claros y guías de migración antes de eliminarlos.

