← Recursos
Guía · Por Sebastian · @jsramirezdev · Noviembre 2026

Sistemas que no se caen

Un sistema que no se cae no es uno que nunca falla, es uno que sigue funcionando cuando algo falla. Esta guía reúne 7 principios y un checklist de 15 puntos para diseñar así, sin importar tu stack.

Por qué se caen los sistemas

Casi nunca por un solo error grande. Se caen por cadenas de fallos pequeños: un servicio lento que acumula conexiones, un reintento que multiplica la carga, un despliegue sin plan de reversa.

  • Un componente falla y arrastra a los demás (falla en cascada).
  • Un pico de tráfico supera lo que el sistema aguanta y nada lo frena.
  • Un cambio llega a producción sin forma de deshacerlo rápido.
  • Nadie se entera hasta que lo reporta un usuario.

Cómo usar esta guía

Lee los 7 principios en orden, aplica el checklist final a un sistema real que ya tengas y marca qué te falta. Empieza por lo que más duele hoy, no por todo a la vez.

1. Diseña para el fallo

Asume que cada red, disco, servicio y dependencia externa va a fallar algún día. La pregunta de diseño cambia de “¿cómo evito que falle?” a “¿qué pasa cuando falle?”.

  • Lista las dependencias de cada flujo crítico (base de datos, pagos, correo, APIs de terceros).
  • Para cada una responde: ¿qué ve el usuario si no responde? ¿Se pierde información? ¿Se recupera sola?
  • Define qué flujos son críticos (login, pago, compra) y cuáles pueden esperar (recomendaciones, analytics).

Si no tienes respuesta para alguna dependencia, ahí está tu próxima caída.

2. Elimina los puntos únicos de falla

Un punto único de falla es cualquier pieza que, si cae, tumba todo. Se resuelve con redundancia donde duele y con estado fuera de las instancias.

  • Varias instancias detrás de un balanceador, en al menos dos zonas de disponibilidad (en AWS: Multi-AZ).
  • Base de datos con réplica y failover automático; prueba el failover, no solo lo configures.
  • Servicios sin estado: sesiones y archivos en Redis o S3, no en el disco de una instancia.
  • Dependencias externas: ten un plan B (segundo proveedor o modo degradado) para las críticas.
  • También personas: si solo una persona sabe desplegar o recuperar el sistema, es un punto único de falla.

3. Timeouts, reintentos y circuit breakers

Una dependencia lenta es más peligrosa que una caída total, porque retiene hilos y conexiones hasta agotar tu sistema. Tres defensas básicas contra esto:

DefensaQué haceRegla práctica
TimeoutCorta la espera de una llamadaToda llamada de red lleva uno; nunca “sin límite”
Reintento con backoff y jitterReintenta espaciando y con variación aleatoriaMáximo 2 o 3 intentos, solo en operaciones seguras de repetir
Circuit breakerDeja de llamar a un servicio que ya está fallandoAbre tras N fallos seguidos y prueba de nuevo pasado un tiempo

Los reintentos sin límite ni espera convierten un fallo pequeño en una avalancha: cada cliente reintenta y la dependencia nunca se recupera.

4. Desacopla con colas e idempotencia

Si el usuario no necesita la respuesta en el momento, no hagas el trabajo en la misma petición. Una cola absorbe los picos y aísla los fallos entre servicios.

  • Envía a una cola (SQS, RabbitMQ, Kafka) lo que puede esperar: correos, notificaciones, generación de pases, reportes.
  • Configura una dead-letter queue para los mensajes que fallan repetidamente y revisa esa cola con alertas.
  • Haz cada operación idempotente: procesarla dos veces produce el mismo resultado que una. Usa una llave de idempotencia (por ejemplo, el ID del pedido) para no cobrar o enviar dos veces.

La mayoría de las colas (SQS estándar, Kafka por defecto) entregan “al menos una vez”, así que la idempotencia no es opcional.

5. Degrada con elegancia y pon límites

Cuando algo falla o la carga se dispara, es mejor entregar menos que no entregar nada.

  • Modo degradado: si cae el servicio de recomendaciones, muestra el catálogo sin ellas. Si cae un proveedor, usa caché o un valor por defecto.
  • Rate limiting: limita las peticiones por usuario o por API key para que un cliente abusivo no tumbe a los demás.
  • Límite de concurrencia en cada punto de entrada: cada handler, cada consumidor de cola y cada pool de conexiones debe tener un tope de trabajo simultáneo, aunque hoy nadie le mande tanta carga. Un lote que un día llega 100 veces más grande no debe poder lanzar miles de tareas a la vez.
  • Backpressure: si el sistema está saturado, rechaza rápido (un 429 o 503 claro) en lugar de aceptar todo y colapsar.
  • Aislamiento (bulkheads): separa pools de conexiones e hilos por dependencia para que una lenta no consuma los recursos de las otras.
  • Caché con expiración para las lecturas frecuentes, así la base de datos no recibe cada consulta.

Caso real: Bluesky, abril de 2026. Según su post-mortem, un handler era el único sin límite de concurrencia. Un servicio interno nuevo le enviaba lotes de hasta 20 000 elementos, y cada petición lanzaba hasta ese número de tareas contra la caché. Las conexiones abiertas y cerradas a esa velocidad agotaron los puertos, los errores se registraban millones de veces por segundo con escrituras bloqueantes, el runtime creó miles de hilos y el proceso terminó sin memoria y reiniciándose una y otra vez. Una línea de límite habría evitado la cadena.

6. Observabilidad, alertas y SLOs

No puedes arreglar lo que no ves. Debes enterarte de un problema antes que tus usuarios.

PilarQué respondes con élEjemplo
Logs¿Qué pasó exactamente?Logs estructurados con un ID de correlación por petición
Métricas¿Cómo está el sistema ahora?Latencia p95, tasa de errores, saturación, tráfico
Trazas¿Dónde se pierde el tiempo?Traza distribuida entre servicios (OpenTelemetry)
  • Define un SLO por flujo crítico, por ejemplo “99,9 % de los pagos responden en menos de 2 s”.
  • Alerta por síntomas que siente el usuario (errores, latencia), no por cada métrica de CPU.
  • Cada alerta debe tener dueño y un runbook de qué hacer. Una alerta que nadie atiende es ruido.
  • No registres cada error en cada intento cuando el fallo se repite miles de veces por segundo: cuenta los errores con una métrica y registra una muestra. Un log en el camino de fallo puede ser el que termine de hundir el sistema.
  • Separa dos health checks. El de “estoy vivo” (liveness) no mira dependencias: solo dice que el proceso responde. El de “estoy listo para recibir tráfico” (readiness) sí verifica las dependencias críticas. Si el de “vivo” falla porque cayó la base de datos, el orquestador reinicia o retira todas tus instancias a la vez y conviertes un fallo parcial en uno total.

7. Despliegues seguros y pruebas de caos

Gran parte de las caídas las provoca un cambio propio. Haz que desplegar sea aburrido y reversible.

  • Despliegues graduales: canary o blue/green, enviando primero un porcentaje pequeño del tráfico a la versión nueva.
  • Feature flags para apagar una funcionalidad sin volver a desplegar.
  • Rollback en minutos: si revertir toma más de unos minutos, tu proceso es un riesgo.
  • Migraciones de base de datos compatibles hacia atrás, para que la versión anterior siga funcionando durante el cambio.
  • Pruebas de carga antes de lanzamientos grandes, y pruebas de caos pequeñas (apagar una instancia, simular una dependencia caída) en horario controlado.
  • Postmortems sin culpables después de cada incidente, con acciones concretas y dueño.

Checklist de 15 puntos

Márcalos en un sistema real. Cada casilla sin marcar es una caída posible.

  • Tengo identificados los flujos críticos y sus dependencias.
  • Sé qué ve el usuario cuando cada dependencia falla.
  • No hay un solo servidor, base de datos o persona de la que dependa todo.
  • Corro en al menos dos zonas de disponibilidad y mis servicios no guardan estado local.
  • Toda llamada de red tiene timeout, y los reintentos tienen límite, backoff y jitter.
  • Uso circuit breakers en las dependencias externas.
  • Lo que puede esperar va a una cola, con dead-letter queue.
  • Mis operaciones son idempotentes.
  • Tengo rate limiting y sé rechazar carga a tiempo.
  • Cada handler, consumidor y pool de conexiones tiene un límite de concurrencia.
  • Existe un modo degradado para los flujos críticos.
  • Tengo logs, métricas y trazas, y alertas con dueño y runbook.
  • Mis health checks separan “estoy vivo” de “estoy listo para recibir tráfico”.
  • Despliego de forma gradual y puedo revertir en minutos.
  • Hago postmortems después de cada incidente y cierro las acciones.

Siguiente paso

Elige los tres puntos sin marcar que más riesgo te generan y resuélvelos esta semana. Un sistema resiliente se construye de a poco, empezando por lo que más duele.

Si te sirvió, sígueme en @jsramirezdev y comparte esta guía con quien diseñe sistemas contigo.

Fuente del caso de Bluesky: resumen del post-mortem en ilert, basado en el post-mortem de su equipo de ingeniería.

Dev Metódico Newsletter

Deja tu correo y te llegan los próximos recursos.