Cambios de API

Cómo deprecar una API sin perder a sus desarrolladores

7 min de lectura

Deprecar una API es anunciar que algo todavía funciona hoy y dejará de funcionar en una fecha declarada, y luego mantener las dos mitades de esa promesa. La mayoría de las deprecaciones fallan en la segunda mitad: la fecha se desliza en silencio, o llega y los llamantes que nunca vieron el aviso se enteran por un error. Una deprecación está terminada cuando cada llamante afectado ha migrado o se le ha dicho, individualmente, que no lo ha hecho.

¿Qué es la deprecación de una API?

La deprecación es el período entre anunciar que un endpoint, campo o versión va a desaparecer y realmente eliminarlo. Durante ese período el comportamiento antiguo sigue funcionando, la documentación dice que se va, y cada respuesta lleva un aviso legible por máquina. La eliminación es el evento separado, posterior, a menudo llamado sunset. Los dos se confunden, y la confusión es donde ocurre el daño: “deprecated” empieza a significar “puede que ya no esté”, y los llamantes dejan de confiar en ninguna de las dos palabras.

TérminoSignificadoEn qué pueden confiar los llamantes
DeprecatedAnunciado como que se va, sigue funcionandoComportamiento completo hasta la fecha de sunset
SunsetLa fecha en que deja de funcionarNada después de esta fecha
Retired / eliminadoSe fue; las peticiones fallanUn error, idealmente uno que nombre el reemplazo
LegacyIndefinido. Evita la palabraNada, que es el problema

¿Cuánto debería durar un período de deprecación?

Lo suficiente para que un llamante se entere y haga el trabajo, medido desde cuándo le llegó el aviso y no desde cuándo lo escribiste. Noventa días es el piso habitual para una API web pública. Doce meses es normal para cualquier cosa embebida en software que instalan usuarios finales, porque la corrección también tiene que pasar por su proceso de lanzamiento. La guía de versionado de Google, AIP-185, pide un período de transición razonable y recomienda 180 días incluso antes de retirar funcionalidad beta, y Kubernetes documenta su política de deprecación en conteo de lanzamientos en vez de meses, que es la unidad correcta cuando tus llamantes actualizan por versión.

Elige un período, escríbelo como política, y deja de decidirlo por cambio. Una política publicada convierte cada deprecación de una negociación en la aplicación de una regla.

Escribir la política de deprecación cubre el inicio de la ventana; retirar una versión de API cubre el aviso separado que se necesita al final, cuando el período realmente se acaba y la versión deja de funcionar.

El calendario de deprecación

Cuatro fechas, anunciadas juntas el primer día. Cada una es una entrada de changelog separada cuando llega, así que la historia se cuenta cuatro veces a quien solo lee el changelog.

  1. Anunciar. La entrada dice qué se deprecia, por qué, qué lo reemplaza, y la fecha de sunset. La documentación de lo antiguo gana un banner que enlaza a la migración. Las respuestas ganan los headers descritos más abajo.
  2. Recordar, a mitad de camino. Una segunda entrada, y un mensaje directo a todo llamante que siga usando el comportamiento antiguo. Este es el paso que necesita datos de uso: si no puedes listar quién sigue llamando al endpoint deprecado, no puedes hacerlo, y vale la pena arreglar eso antes de la próxima deprecación.
  3. Apagón breve, poco antes de la fecha. Devuelve errores para el comportamiento antiguo durante una ventana corta, una hora o un día, luego restáuralo. Los llamantes que se perdieron todos los avisos se enteran ahora, mientras todavía hay tiempo. GitHub usó apagones programados antes de retirar la autenticación por contraseña de la API, y es el paso individual más efectivo de esta lista.
  4. Sunset. Elimínalo. El error que lo reemplaza nombra el reemplazo y enlaza la guía de migración. Mantén el error en su sitio durante mucho tiempo; un 404 no le dice nada a un llamante.

¿Qué debería decir un aviso de deprecación?

Un aviso de deprecación dice qué se va, cuándo deja de funcionar, qué usar en su lugar, y a quién afecta. Aquí la forma, rellenada:

GET /v1/reports/daily está deprecado y deja de funcionar el 1 de marzo de 2027. Se reemplaza por GET /v2/reports?granularity=day, que devuelve los mismos datos con un esquema estable y paginación. Afecta a las 214 integraciones que llamaron al endpoint v1 en los últimos 30 días; si la tuya es una de ellas, también recibirás este aviso por correo. Guía de migración: [enlace]. Nada cambia hasta el 1 de marzo de 2027. A partir de esa fecha el endpoint v1 devuelve 410 Gone con un enlace a esta entrada.

Cada frase lleva algo que la lectora necesita. El número de integraciones afectadas le dice a cada lectora si debe seguir leyendo. “Nada cambia hasta” es la frase que deja que quienes no están afectados cierren la pestaña. La página de ejemplos de changelog recopila entradas de equipos que escriben esta forma con consistencia, y vale la pena leer tres antes de escribir la primera propia.

¿Qué headers debería enviar un endpoint deprecado?

Envía Deprecation, Sunset y un Link al sucesor, en cada respuesta del endpoint deprecado, desde el día del anuncio. El header Deprecation lleva la fecha en que entró en vigor la deprecación; el header Sunset lleva la fecha en que el endpoint deja de responder; Link: <url>; rel="successor-version" apunta a qué usar en su lugar.

HTTP/1.1 200 OK
Deprecation: @1756425600
Sunset: Mon, 01 Mar 2027 00:00:00 GMT
Link: <https://api.example.com/v2/reports>; rel="successor-version"
Link: <https://example.com/changelog/daily-reports>; rel="deprecation"

La mayoría de los llamantes nunca leerán los headers por sí mismos. Su valor está en que el cliente HTTP, el gateway o el monitoreo de un llamante sí puede, lo que convierte tu deprecación en una alerta de su lado en vez de una página del tuyo. Los SDKs que envíes deberían registrar una advertencia cuando vean uno.

¿A quién se le avisó, y cómo lo sabes?

Este es el paso que decide si el sunset es tranquilo o un incidente de soporte, y es el más difícil de hacer solo con un changelog. Una entrada de changelog le avisa a todo el que lee el changelog. Una deprecación tiene que llegar a la gente concreta cuyo código va a fallar, y la forma habitual de encontrarla son los mismos datos de uso que necesita el recordatorio a mitad de camino: las claves de API, apps o cuentas que llamaron al comportamiento deprecado recientemente.

El ciclo que ejecutamos: la entrada se redacta a partir del pull request que añade la deprecación, una persona revisa la redacción y la fecha, y una vez publicada la entrada misma es la notificación. Cualquier persona cuyo feedback en el widget sobre el problema, o petición del reemplazo, se convirtió en un issue de GitHub que cierra el pull request recibe un comentario en ese issue diciendo que se lanzó, con un enlace a la entrada. Feed y widget sirven la misma entrada a todos los demás, junto con cada otra entrada del changelog de API. Lo que no hacemos es dejar que la deprecación se vuelva “lanzada” antes de que una persona la haya publicado; un aviso con la fecha equivocada es peor que ningún aviso.

Sea cual sea tu herramienta, la pregunta que debes poder responder el día del sunset es: ¿qué llamantes seguían usando esto la semana pasada, y a cuáles de ellos les avisamos directamente? Si la respuesta es “publicamos algo sobre eso”, el sunset no está listo.

¿Cuál es la diferencia entre deprecar y versionar?

Versionar es cómo mantienes disponible el comportamiento antiguo mientras existe el nuevo; deprecar es cómo retiras el antiguo. Una versión nueva de API sin política de deprecación para la anterior es un compromiso de mantener las dos para siempre. Una deprecación sin versionado es un cambio que rompe algo con retraso. Necesitas ambos, y la versión es la mitad más fácil. GraphQL es la excepción que vale la pena nombrar: normalmente no hay ningún número de versión que subir, y deprecación de esquema en GraphQL cubre cómo un único esquema compartido retira un campo con una directiva en su lugar.

FAQ

¿Debería un endpoint deprecado seguir funcionando exactamente igual que antes? Sí, hasta la fecha de sunset. Los únicos cambios permitidos son los headers añadidos y, cerca del final, un apagón programado que anunciaste con antelación.

¿Qué código de estado debería devolver un endpoint retirado? 410 Gone, con un cuerpo y un header Link apuntando al reemplazo y a la entrada de changelog. 404 dice que la URL nunca existió, lo cual es falso y no ayuda.

¿Se puede acortar un período de deprecación? Solo por seguridad. Si el comportamiento antiguo es explotable, dilo, acorta el período, y avisa a cada llamante afectado directamente en vez de confiar en el changelog.

¿Necesito deprecar un campo, o solo endpoints enteros? Campos, parámetros, valores de enum, valores por defecto y headers necesitan todos el mismo trato, porque cada uno puede romper a un llamante correcto. Un campo eliminado es la deprecación más común y la que más se salta.


Las afirmaciones técnicas de este artículo no se han revisado de forma independiente. Si algo está mal, avísanos y lo corregiremos.

Relacionado en changeloop: Documentación para desarrolladores, Ejemplos de changelog

changeloop
El equipo que crea un changelog que cierra el círculo. Tus usuarios lo piden, tu equipo lo publica y quien lo pidió se entera.