Si pulsas el botón de pago en una tienda en línea y lo único que ves durante un buen rato es el indicador de carga dando vueltas, ¿qué está pasando por detrás? En el software actual, donde numerosos servicios se llaman entre sí, es fácil que un fallo en un punto se propague en cadena. Para evitarlo, existe una técnica de diseño que bloquea temporalmente las solicitudes dirigidas al servicio que tiene problemas. Se conoce como «patrón de interruptor de circuito (Circuit Breaker Pattern)».
En pocas palabras, el patrón de interruptor de circuito funciona como un interruptor de seguridad que bloquea automáticamente las llamadas cuando se suceden los fallos y las vuelve a permitir cuando se recupera el servicio llamado. Su nombre viene del interruptor eléctrico que se dispara por sí solo cuando circula demasiada corriente. El patrón se dio a conocer ampliamente cuando Michael T. Nygard lo presentó en su libro Release It!, publicado en 2007.
En este artículo veremos, por orden, cómo surgió el patrón de interruptor de circuito, sus tres estados (cerrado, abierto y semiabierto), cómo se usa en sistemas reales y qué conviene tener en cuenta al diseñarlo.
Un interruptor que se activa por sí solo para impedir que se propaguen los fallos
Origen del patrón de interruptor de circuito

Detrás de una aplicación hay varios servicios que se reparten funciones como la gestión de usuarios, los productos, los pagos y los envíos, y se llaman entre sí a través de la red. En una estructura así, basta con que un servicio se ralentice para que también se ralenticen los que esperan su respuesta.
(1) Fallos en cascada a partir de un fallo en un solo punto
Si el servicio de pagos no responde, el servicio de pedidos se queda bloqueado a la espera de una respuesta, y la interfaz que llamó al servicio de pedidos también se bloquea. Este fenómeno, en el que los fallos se propagan en cadena, se denomina fallo en cascada (Cascading Failure).
(2) Recursos ocupados durante la espera
Cada solicitud que espera una respuesta de un servicio que no responde mantiene ocupados hilos, conexiones y memoria. Si las solicitudes siguen acumulándose, estos recursos se agotan y hasta las funciones que operaban con normalidad dejan de estar disponibles. El servicio averiado ni siquiera tiene tiempo para recuperarse debido a la avalancha de solicitudes reenviadas.
(3) Una idea tomada del interruptor eléctrico
Cuando circula una corriente excesiva, el interruptor eléctrico abre el circuito para evitar que se quemen los cables. Nygard trasladó este principio al software y propuso cortar las llamadas cuando los fallos se sucedieran. En 2014, Martin Fowler publicó un artículo en el que explicó el patrón, lo que contribuyó a difundirlo entre los desarrolladores.
Los tres estados del interruptor de circuito: cerrado, abierto y semiabierto

El interruptor de circuito es un pequeño mecanismo de supervisión que se interpone entre quien hace la llamada y el servicio que la recibe. Lleva la cuenta de las solicitudes que tienen éxito y de las que fallan. Según los criterios establecidos, alterna entre tres estados para dejar pasar o bloquear las solicitudes.

- Cerrado (Closed). Es el estado habitual. Deja pasar las solicitudes con normalidad y registra el número o la tasa de fallos.
- Abierto (Open). El interruptor pasa a este estado cuando los fallos superan el umbral. Devuelve de inmediato un error o una respuesta alternativa sin llamar al servicio.
- Semiabierto (Half-Open). Una vez transcurrido el tiempo establecido, solo se envían unas pocas solicitudes de prueba para comprobar si el servicio se ha recuperado.
- Fallo rápido (Fail Fast). Consiste en comunicar el fallo de inmediato para ahorrar recursos y evitar esperas prolongadas.
(1) El estado cerrado contabiliza los fallos
El nombre «cerrado» alude al estado en el que el circuito eléctrico está conectado y deja pasar la corriente. Se fija un criterio, por ejemplo, «que falle al menos la mitad de las últimas 100 solicitudes», y en cuanto se supera ese umbral, el interruptor pasa al estado abierto.
(2) El estado abierto evita la espera
En el estado abierto, las solicitudes no llegan al servicio averiado. El usuario recibe un aviso de inmediato, sin tener que esperar mucho, y el servicio averiado queda libre de la avalancha de solicitudes y gana tiempo para recuperarse.
(3) El estado semiabierto comprueba la recuperación con cautela
Una vez que el interruptor ha permanecido abierto durante el tiempo establecido, pasa al estado semiabierto y solo deja pasar unas pocas solicitudes. Si las solicitudes de prueba tienen éxito, vuelve al estado cerrado. Si vuelven a fallar, regresa al estado abierto y se repite la espera.
Uso en sistemas reales

El patrón de interruptor de circuito se adoptó primero en grandes empresas de internet donde numerosos servicios dependen unos de otros. Hoy se puede usar fácilmente mediante bibliotecas para diversos lenguajes de programación.
(1) Hystrix de Netflix
En 2012, Netflix publicó Hystrix, una biblioteca de Java que incluía la función de interruptor de circuito. En 2018 se dejó de desarrollar nuevas funciones para Hystrix. Desde entonces, Resilience4j se usa mucho en el ecosistema de Java y Polly en el de .NET.
(2) Una respuesta alternativa para suplir al servicio interrumpido
Cuando se abre el circuito, se puede devolver una respuesta alternativa preparada de antemano, llamada Fallback, en lugar de mostrar únicamente un error. Por ejemplo, si se interrumpe el servicio de recomendaciones personalizadas, se puede mostrar una lista de elementos populares en lugar de la lista personalizada para que la pantalla no quede vacía.
(3) Otros mecanismos de protección que se usan en conjunto
El interruptor de circuito suele combinarse con el tiempo de espera máximo (Timeout), que pone fin a la espera al cabo del tiempo establecido, el reintento (Retry), que vuelve a enviar las solicitudes fallidas dejando un intervalo, y el patrón de mamparo (Bulkhead), que divide los recursos como los mamparos de un barco para impedir que un fallo en una parte se propague a otra.
Aspectos que conviene tener en cuenta al diseñarlo

El interruptor de circuito requiere algo más que activarlo. Según cómo se fijen los criterios, puede servir de escudo para el sistema o convertirse en un obstáculo que bloquee funciones que operan con normalidad.
(1) Ajustar la sensibilidad del interruptor
Si el umbral es demasiado bajo, incluso una fluctuación momentánea abre el circuito y bloquea hasta las solicitudes normales. Si es demasiado alto, el circuito solo se abre cuando el fallo ya se ha propagado. Por eso, junto con la tasa de fallos, se fija el número mínimo de solicitudes necesario para tomar una decisión y el tiempo de respuesta a partir del cual una respuesta lenta se considera un fallo.
(2) Decidir qué se cuenta como fallo
Por lo general, los errores que se producen cuando el usuario introduce un valor incorrecto se excluyen del recuento, ya que su origen no está en un fallo del servicio llamado. Para evitar que el circuito se abra indebidamente, solo deben contabilizarse los fallos que reflejan el estado de ese servicio, como los errores del servidor o los retrasos en la respuesta.
(3) Supervisar el estado del circuito
Saber cuándo se abrió y se cerró el circuito proporciona una señal importante para detectar fallos. Si se registran los cambios de estado y se muestran mediante alertas y paneles de control, el personal de operaciones puede identificar rápidamente qué servicio tiene problemas.
En definitiva, el patrón de interruptor de circuito es una técnica para contener los fallos, no para eliminarlos. El primer paso para entenderlo es esta idea sencilla: conviene suspender temporalmente las llamadas al servicio averiado y darle tiempo para recuperarse, en vez de mantener a todos esperando su respuesta.