Inicio/Blog/APIs confiables
Arquitectura de APIs Resilientes

Construyendo APIs confiables para redes de alta variabilidad

En redes móviles, satelitales, rurales, Wi-Fi saturado o vehículos en movimiento, la llamada puede llegar al servidor y perderse la respuesta. El ancho de banda cambia durante el upload y la reconexión usa otra ruta. El contrato debe volver segura esa incertidumbre.

Diseñe para variabilidad, no para el promedio

Mida DNS, conexión, TLS, upload, procesamiento, first byte, descarga, pérdida, reconexión y cambios de radio. Segmente por país, operador/ASN, red, app, dispositivo, endpoint, payload e intento. p50 oculta a quien cruza repetidamente el timeout.

RTT altoCada handshake y dependencia secuencial es costosa. Reutilice conexión, reduzca llamadas y agrupe con límites.
Pérdida y cambio de rutaLa conexión se detiene o reinicia y el cliente no sabe si el write confirmó.
Ancho de banda variableUna respuesta pequeña funciona; medios o listas ilimitadas fallan a mitad.
Disponibilidad intermitenteLa app alterna online, captive, degradada, background y offline; la intención sobrevive al proceso.

Asigne un deadline integral

La operación necesita un presupuesto, no 30 segundos por salto. Reserve DNS/connect/TLS, primer intento, retry opcional, parsing y UI. Propague el saldo downstream y cancele trabajo abandonado. Separe timeout de conexión y request/idle.

DNS
Connect
TLS
Try 1
Jitter
Try 2
Límite
Parse
UI

Retry depende de método, falla y presupuesto

Repita GET/HEAD ante fallas transitorias. PUT/DELETE pueden ser idempotentes por contrato, pero una implementación puede disparar efectos externos. No repita POST/PATCH sin idempotency contract. Validación, autenticación, autorización, conflicto y not-found permanente no son pérdida de paquetes.

Backoff exponencial acotado con full jitter
T+0Intento 1Envíe request ID, deadline e idempotency key cuando corresponda.
falla transitoria → aleatorio 0..base
T+Δ1Intento 2Reutilice ID lógico y deténgase si presupuesto/política no permiten.
aleatorio 0..min(cap, base × 2²)
T+Δ2Intento finalDevuelva estado recuperable, encole o muestre falla. Nunca repita sin límite.

Ubique retries en una sola capa

SDK 3x, gateway 3x y servicio 3x producen 27 llamadas. Elija la capa que conoce semántica y presupuesto. Use retry quota/token bucket, límites, full jitter, Retry-After y desactive ante falla sostenida.

ResultadoInterpretaciónPolíticaContrato servidorEvitar
Conexión perdida sin respuestaOutcome del write desconocido.Retry solo seguro/idempotente o keyed.Estado consultable por key/ID.Crear compra duplicada.
408 / timeoutNo completó en contexto.Retry acotado si queda budget.Detener trabajo y deduplicar.Reiniciar operación larga.
429 / cuotaEl caller excedió política.Respetar tiempo y regular tráfico.Política legible por máquina.Todos repiten juntos.
502/503/504Upstream, overload o gateway transitorio.Retry pequeño con jitter; fallback de lectura.Load shedding y Retry-After.Retry storm.
409 conflictoEstado actual rechaza cambio.Leer y conciliar.Problem details y revisión.Sobrescribir concurrencia.
4xx validación/authRequest o autoridad debe cambiar.Sin retry de transporte.Tipo, campos, remedio y request ID.Gastar batería repitiendo.

La idempotencia es una máquina de estados

El cliente crea una key de alta entropía ligada a principal y ruta. El servidor guarda key, fingerprint, estado, operación/recurso, resultado, timestamps y expiración. Misma key/payload devuelve outcome original; payload distinto se rechaza. Duplicados concurrentes esperan o reciben “en progreso”. Persista el registro con el efecto de forma atómica.

El trabajo largo es asíncrono

Devuelva 202 Accepted con URL de operación. Exponga pending/running/succeeded/failed/cancelled, tiempos, resultado y problem detail. Polling usa backoff y ETag, o evento firmado. No mantenga una conexión móvil abierta durante minutos.

La paginación comienza con orden estable

Cada lista nace paginada. El cursor liga query, filtros, sort, snapshot/boundary, dirección y última tupla, por ejemplo (updated_at, id). Tokens son opacos e íntegros. Offset sirve para conjuntos pequeños/estáticos; colecciones mutables producen duplicados y saltos.

Permita pedir menos

Use page size acotado, field masks, summaries, filtros, delta sync, updated_since estable y medios separados. El cliente necesita la próxima pantalla accionable, no todo el dominio.

La compresión se negocia y mide

Use Accept-Encoding y Vary: Accept-Encoding. Comprima JSON, texto, protobuf y SVG sobre un umbral. No recomprima JPEG/AVIF/video. Compare Brotli, gzip y Zstandard por tamaño, CPU, batería y latencia.

Caché y revalidación evitan descargas

Use Cache-Control, ETag, If-None-Match y Last-Modified. Separe público/personal, defina Vary y freshness. Datos stale requieren as_of y acciones limitadas. Cache-Status ayuda a depurar.

Las transferencias grandes se reanudan

Upload por partes usa ID, offset/part, checksum, expiración, metadata y finalize. Downloads usan ranges y validators. Repita partes faltantes. tus es una opción establecida. No complete antes de verificar longitud y digest.

La degradación es un contrato de producto

Sirva menosPágina menor, summary, sin thumbnail, menor precisión, enriquecimiento diferido o caché.
Encole intenciónComando local con operation ID, key, versión, expiración, estado y política de conflicto.
Bloquee acciones riesgosasSi auth, precio, stock, saldo o seguridad están stale, permita lectura y bloquee writes irreversibles.
Priorice tráfico centralAuth, seguridad, pago, metadata de sync y texto antes de analytics e imágenes.
Haga load sheddingRechace trabajo opcional temprano y preserve capacidad crítica.
Muestre estado realOffline, sincronizando, pendiente, stale, falló, conflicto y confirmado son distintos.

Use errores legibles por máquina

RFC 9457 define type, title, status, detail e instance. Agregue código estable, campos, retryability, correlation ID y remediación. No exponga stack ni obligue a parsear texto localizado.

El transporte no reemplaza semántica

HTTP/3 sobre QUIC mejora pérdida y cambios; prioridad HTTP comunica urgencia. Reuso, TLS resumption, edge y menos secuencias ayudan. Nada evita efectos duplicados, listas ilimitadas, errores ambiguos o writes stale.

Observe intentos, no solo requests

Trace una operación por operation ID y request ID por intento. Registre timings, bytes, compresión, caché, red, fase del timeout, retry, idempotencia, cursor, stale mode, cola y outcome. Mida amplificación, deduplicación, conclusión por red, datos/batería y p95/p99.

Lo que construiría

SDK con deadline, timeouts, clasificación, full-jitter, quota, keys, polling, cursor, caché condicional, uploads reanudables, outbox, conflictos y telemetría. Servidor con storage idempotente, problem details, load shedding, paginación, field masks, operaciones, ETags, cancelación y trazas por intento.

El principio

Una API confiable no finge que la red es confiable. Vuelve recuperable cada outcome incierto, acota retries, deduplica writes, reanuda transferencias y hace visible el estado degradado.

Lecturas relacionadas

Artículo sobre APIs confiables en redes variables, retries, backoff, jitter, idempotencia, compresión, paginación, caché, reanudación, colas offline y degradación.