Aprende el teorema CAP de Eric Brewer como un modelo mental práctico: cómo consistencia, disponibilidad y particiones influyen en las decisiones de sistemas distribuidos.

Cuando almacenas los mismos datos en más de una máquina, ganas velocidad y tolerancia a fallos—pero también heredas un problema nuevo: desacuerdo. Dos servidores pueden recibir actualizaciones distintas, los mensajes pueden llegar tarde o no llegar, y los usuarios pueden leer respuestas diferentes según qué réplica atiendan. CAP se hizo popular porque da a los ingenieros una forma clara de hablar sobre esa realidad desordenada sin ambigüedades.
Eric Brewer, científico informático y cofundador de Inktomi, presentó la idea central en 2000 como una afirmación práctica sobre sistemas replicados bajo fallo. Se difundió rápido porque encajaba con lo que los equipos ya veían en producción: los sistemas distribuidos no solo fallan apagándose; fallan dividiéndose.
CAP es más útil cuando las cosas van mal—especialmente cuando la red no se comporta. En un día sano, muchos sistemas pueden parecer suficientemente consistentes y disponibles. La prueba de fuego es cuando las máquinas no pueden comunicarse de forma fiable y debes decidir qué hacer con lecturas y escrituras mientras el sistema está dividido.
Esa perspectiva es la razón por la que CAP se convirtió en modelo de referencia: no discute sobre mejores prácticas; obliga a una pregunta concreta—¿qué sacrificaremos durante una partición?
Al terminar este artículo deberías poder:
CAP perdura porque convierte el vago “lo distribuido es difícil” en una decisión que puedes tomar—y defender.
Un sistema distribuido es, en términos simples, muchos ordenadores intentando actuar como uno solo. Puedes tener varios servidores en distintos racks, regiones o zonas de nube, pero para el usuario es “la app” o “la base de datos”.
Para que ese sistema compartido funcione a escala real, normalmente replicamos: mantenemos varias copias de los mismos datos en máquinas distintas.
La replicación es popular por tres razones prácticas:
Hasta aquí, la replicación parece un triunfo claro. El inconveniente es que la replicación crea una nueva tarea: mantener todas las copias de acuerdo.
Si cada réplica pudiera siempre hablar con las demás instantáneamente, podrían coordinar actualizaciones y mantenerse alineadas. Pero las redes reales no son perfectas. Los mensajes pueden retrasarse, perderse o enrutarse sorteando fallos.
Cuando la comunicación está sana, las réplicas suelen intercambiar actualizaciones y converger en el mismo estado. Pero cuando la comunicación se rompe (incluso temporalmente), puedes acabar con dos versiones válidas de “la verdad”.
Por ejemplo, un usuario cambia su dirección de envío. La réplica A recibe la actualización, la réplica B no. Ahora el sistema tiene que responder a una pregunta aparentemente simple: ¿cuál es la dirección actual?
Esta es la diferencia entre:
El pensamiento CAP empieza exactamente aquí: una vez que existe replicación, el desacuerdo bajo fallo de comunicación no es un caso borde—es el problema central de diseño.
CAP es un modelo mental de lo que los usuarios realmente sienten cuando un sistema está distribuido en varias máquinas (a menudo en varias ubicaciones). No describe “buenos” o “malos” sistemas—solo la tensión que debes gestionar.
La consistencia trata sobre el acuerdo. Si actualizas algo, ¿reflejará la siguiente lectura (desde cualquier lugar) esa actualización?
Desde el punto de vista del usuario, es la diferencia entre “acabo de cambiarlo y todos ven el nuevo valor” frente a “algunas personas todavía ven el valor antiguo por un rato”.
Disponibilidad significa que el sistema responde a peticiones—lecturas y escrituras—con un resultado de éxito. No “el más rápido posible”, sino “no te rechaza”.
Durante problemas (un servidor caído, un fallo de red), un sistema disponible sigue aceptando peticiones, incluso si debe responder con datos algo desactualizados.
Una partición es cuando la red se divide: las máquinas funcionan, pero los mensajes entre algunas de ellas no pueden pasar (o llegan demasiado tarde para ser útiles). En sistemas distribuidos, no puedes tratar esto como imposible—debes definir el comportamiento cuando ocurra.
Imagina dos tiendas que venden el mismo producto y comparten “1 unidad de inventario”. Un cliente compra el último artículo en la Tienda A, así que A escribe inventario = 0. Al mismo tiempo, una partición de red impide que la Tienda B lo sepa.
Si B permanece disponible, puede vender un artículo que ya no tiene (aceptando la venta mientras está particionada). Si B aplica consistencia, puede rechazar la venta hasta confirmar el inventario más reciente (negando servicio durante la partición).
Una “partición” no es solo “Internet está caído”. Es cualquier situación donde partes de tu sistema no pueden comunicarse de forma fiable—aunque cada parte siga ejecutándose correctamente.
En un sistema replicado, los nodos intercambian constantemente mensajes: escrituras, acuses, latidos, elecciones de líder, lecturas. Una partición es lo que ocurre cuando esos mensajes dejan de llegar (o llegan demasiado tarde), creando desacuerdo sobre la realidad: “¿Se aplicó esa escritura?” “¿Quién es el líder?” “¿Está vivo el nodo B?”
La comunicación puede fallar de formas desordenadas y parciales:
El punto importante: las particiones suelen ser degradación, no una caída limpia. Para la aplicación, “lo bastante lento” puede ser indistinguible de “caído”.
Al añadir más máquinas, más redes, más regiones y más piezas móviles, hay simplemente más oportunidades de que la comunicación se rompa temporalmente. Incluso si los componentes individuales son fiables, el sistema global experimenta fallos porque tiene más dependencias y más coordinación entre nodos.
No necesitas asumir una tasa de fallos exacta para aceptar la realidad: si tu sistema funciona lo bastante tiempo y abarca suficiente infraestructura, ocurrirán particiones.
Tolerancia a particiones significa que tu sistema está diseñado para seguir operando durante una división—incluso cuando los nodos no pueden ponerse de acuerdo o confirmar lo que el otro lado ha visto. Eso fuerza una elección: seguir atendiendo peticiones (arriesgando inconsistencia) o detener/rechazar algunas peticiones (preservando consistencia).
Una vez que tienes replicación, una partición es simplemente una ruptura de comunicación: dos partes de tu sistema no pueden hablarse con fiabilidad durante un tiempo. Las réplicas siguen en marcha, los usuarios siguen haciendo clic, y tu servicio sigue recibiendo peticiones—pero las réplicas no pueden acordar la verdad más reciente.
Esa es la tensión CAP en una frase: durante una partición, debes elegir priorizar Consistencia (C) o Disponibilidad (A). No obtienes ambas al mismo tiempo.
Estás diciendo: “prefiero estar correcto a ser rápido”. Cuando el sistema no puede confirmar que una petición mantendrá todas las réplicas en sincronía, debe fallar o esperar.
Efecto práctico: algunos usuarios verán errores, timeouts o mensajes de “inténtalo de nuevo”—especialmente para operaciones que cambian datos. Esto es común cuando prefieres rechazar un pago antes que cobrar dos veces, o bloquear una reserva de asiento antes que vender de más.
Estás diciendo: “prefiero responder a bloquearme”. Cada lado de la partición seguirá aceptando peticiones, incluso si no puede coordinarse.
Efecto práctico: los usuarios obtienen respuestas exitosas, pero los datos que leen pueden estar obsoletos, y las actualizaciones concurrentes pueden conflictar. Luego dependes de la reconciliación posterior (reglas de merge, last-write-wins, revisión manual, etc.).
Esto no es siempre un ajuste global. Muchos productos mezclan estrategias:
El momento clave es decidir—por operación—qué es peor: bloquear a un usuario ahora o arreglar una verdad en conflicto después.
El lema “elige dos” es memorable, pero a menudo induce a error al hacer creer que CAP es un menú de tres características donde solo puedes quedarte con dos para siempre. CAP trata de lo que ocurre cuando la red deja de cooperar: durante una partición (o cualquier cosa que parezca una), un sistema distribuido debe elegir entre devolver respuestas consistentes y mantenerse disponible para cada petición.
En sistemas reales distribuidos, las particiones no son una opción que puedas desactivar. Si tu sistema abarca máquinas, racks, zonas o regiones, los mensajes pueden retrasarse, perderse, reordenarse o enrutarse de forma extraña. Eso es una partición desde la perspectiva del software: los nodos no pueden acordar qué está ocurriendo.
Incluso si la red física está bien, fallos en otras partes crean el mismo efecto—nodos sobrecargados, pausas de GC, vecinos ruidosos, problemas de DNS, balanceadores inestables. El resultado es el mismo: algunas partes del sistema no pueden hablar con otras lo suficiente para coordinarse.
Las aplicaciones no experimentan la “partición” como un evento binario y ordenado. Experimentan picos de latencia y timeouts. Si una petición agota el tiempo tras 200 ms, no importa si el paquete llegó en 201 ms o nunca llegó: la app debe decidir qué hacer a continuación. Desde la app, la comunicación lenta suele ser indistinguible de la comunicación rota.
Muchos sistemas reales son mayormente consistentes o mayormente disponibles, según configuración y condiciones de operación. Timeouts, políticas de reintento, tamaños de quórum y opciones de “leer tus propias escrituras” pueden desplazar el comportamiento.
En condiciones normales, una base de datos puede parecer fuertemente consistente; bajo estrés o fallos cross-región, puede empezar a fallar peticiones (favoreciendo consistencia) o devolver datos antiguos (favoreciendo disponibilidad).
CAP trata menos de etiquetar productos y más de entender el intercambio que haces cuando aparece el desacuerdo—especialmente cuando ese desacuerdo es causado por la simple lentitud.
Las discusiones CAP suelen hacer que la consistencia parezca binaria: o “perfecta” o “vale todo”. Los sistemas reales ofrecen un menú de garantías, cada una con una experiencia de usuario distinta cuando las réplicas discrepan o se rompe un enlace de red.
Consistencia fuerte (a menudo “linearizable”) significa que una vez que una escritura es reconocida, toda lectura posterior—no importa qué réplica—debe devolver esa escritura.
Su coste: durante una partición o cuando una minoría de réplicas no está accesible, el sistema puede retrasar o rechazar lecturas/escrituras para evitar mostrar estados en conflicto. Los usuarios notan esto como timeouts, “inténtalo más tarde” o comportamiento temporal de solo lectura.
Consistencia eventual promete que si no ocurren nuevas actualizaciones, todas las réplicas convergerán. No promete que dos usuarios que leen ahora vean lo mismo.
Lo que los usuarios pueden notar: una foto de perfil recién actualizada que “revierta”, contadores que van retrasados, o un mensaje enviado que no aparece en otro dispositivo por un tiempo corto.
A menudo puedes obtener mejor experiencia sin exigir consistencia fuerte total:
Estas garantías encajan bien con cómo la gente piensa (“no me muestres mis cambios desapareciendo”) y pueden ser más fáciles de mantener durante fallos parciales.
Empieza con promesas al usuario, no con jerga:
La consistencia es una decisión de producto: define qué significa “estar mal” para un usuario y elige la garantía más débil que impida ese mal.
La disponibilidad en CAP no es una métrica para alardear (“cinco nueves”)—es una promesa que haces a los usuarios sobre lo que ocurre cuando el sistema no puede estar seguro.
Cuando las réplicas no pueden ponerse de acuerdo, a menudo eliges entre:
Los usuarios sienten esto como “la app funciona” frente a “la app es correcta”. Ninguno es universalmente mejor; la elección correcta depende de lo que signifique “estar equivocado” en tu producto. Un feed social ligeramente desactualizado es molesto. Un saldo bancario desactualizado puede ser daño.
Dos comportamientos comunes durante la incertidumbre:
Esto no es una elección puramente técnica; es una política. El producto debe definir qué es aceptable mostrar y qué nunca debe ser conjeturado.
La disponibilidad raramente es todo o nada. Durante una división, puedes ver disponibilidad parcial: algunas regiones, redes o grupos de usuarios tienen éxito mientras otros fallan. Esto puede ser un diseño deliberado (seguir atendiendo donde la réplica local está sana) o accidental (desequilibrios de enrutamiento, alcance desigual de quórum).
Un punto medio práctico es el modo degradado: seguir atendiendo acciones seguras mientras limitas las riesgosas. Por ejemplo, permitir navegación y búsqueda, pero desactivar temporalmente “transferir fondos”, “cambiar contraseña” u otras operaciones donde la corrección y unicidad son críticas.
CAP resulta abstracto hasta que lo mapeas a lo que tus usuarios viven durante una partición: ¿prefieres que el sistema siga respondiendo o que pare para evitar devolver/aceptar datos en conflicto?
Imagina dos centros de datos que aceptan pedidos mientras no pueden hablar entre sí.
Si mantienes el flujo de checkout disponible, cada lado puede vender el “último artículo” y sobrevenderás. Eso puede ser aceptable para bienes de poco valor (haciendo backorder o disculpándote), pero doloroso para drops de inventario limitados.
Si eliges consistencia primero, podrías bloquear pedidos nuevos cuando no puedas confirmar stock globalmente. Los usuarios verán “inténtalo más tarde”, pero evitarás vender algo que no puedes cumplir.
El dinero es el dominio clásico donde equivocarse es caro. Si dos réplicas aceptan retiradas independientemente durante una partición, una cuenta puede quedar en negativo.
Los sistemas suelen preferir consistencia en escrituras críticas: rechazar o retrasar acciones si no pueden confirmar el saldo más reciente. Cambiarás algo de disponibilidad (fallos temporales en pagos) por corrección, auditabilidad y confianza.
En chat y feeds sociales, los usuarios toleran pequeñas inconsistencias: un mensaje llega unos segundos tarde, un contador de likes está desfasado, una métrica aparece más tarde.
Aquí, diseñar para disponibilidad suele ser buena elección de producto, siempre que dejes claro qué elementos son “eventualmente correctos” y puedas fusionar actualizaciones limpiamente.
La elección CAP correcta depende del coste de estar equivocado: reembolsos, exposición legal, pérdida de confianza del usuario u caos operacional. Decide dónde puedes aceptar estaleza temporal—y dónde debes fallar cerrado.
Una vez que hayas decidido qué harás durante una partición, necesitas mecanismos que hagan real esa decisión. Estos patrones aparecen en bases de datos, sistemas de mensajería y APIs—aunque el producto nunca nombre “CAP”.
Un quórum es simplemente “la mayoría de las réplicas están de acuerdo”. Si tienes 5 copias, la mayoría es 3.
Al exigir que lecturas y/o escrituras contacten con una mayoría, reduces la probabilidad de devolver datos obsoletos o conflictivos. Por ejemplo, si una escritura debe ser reconocida por 3 réplicas, es más difícil que dos grupos aislados acepten verdades distintas.
El intercambio es velocidad y alcance: si no alcanzas una mayoría (por partición o fallos), el sistema puede rechazar la operación—eligiendo consistencia sobre disponibilidad.
Muchos problemas de “disponibilidad” no son fallos absolutos sino respuestas lentas. Poner un timeout corto puede hacer que el sistema se sienta ágil, pero también aumenta la probabilidad de tratar éxitos lentos como fallos.
Los reintentos pueden recuperarse de fallos transitorios, pero reintentos agresivos pueden sobrecargar un servicio ya estresado. El backoff (esperar un poco más entre reintentos) y el jitter (aleatoriedad) ayudan a que los reintentos no se conviertan en picos de tráfico.
La clave es alinear estos ajustes con tu promesa: “siempre responder” suele implicar más reintentos y fallback; “nunca mentir” suele implicar límites más estrictos y errores claros.
Si eliges mantener disponibilidad durante particiones, las réplicas pueden aceptar actualizaciones distintas y debes reconciliar después. Enfoques comunes incluyen:
Los reintentos pueden crear duplicados: cobrar una tarjeta dos veces o enviar el mismo pedido repetido. La idempotencia lo evita.
Un patrón común es una clave de idempotencia (ID de petición) enviada con cada petición. El servidor almacena el primer resultado y devuelve el mismo resultado para repeticiones—así los reintentos mejoran disponibilidad sin corromper datos.
La mayoría de equipos “eligen” una postura CAP en una pizarra—y luego descubren en producción que el sistema se comporta distinto bajo estrés. Validar significa crear intencionadamente las condiciones donde las compensaciones CAP se hacen visibles, y comprobar que tu sistema reacciona como diseñaste.
No necesitas un corte de cable real para aprender algo. Usa inyección de fallos controlada en staging (y con cuidado en producción) para simular particiones:
El objetivo es responder preguntas concretas: ¿se rechazan o aceptan las escrituras? ¿las lecturas devuelven datos obsoletos? ¿se recupera el sistema automáticamente y cuánto tarda la reconciliación?
Si quieres validar estos comportamientos pronto (antes de invertir semanas en conectar servicios), puede ayudar montar un prototipo realista rápido. Por ejemplo, equipos que usan Koder.ai suelen empezar generando un servicio pequeño (comúnmente un backend Go con PostgreSQL y una UI React) y luego iteran en comportamientos como reintentos, claves de idempotencia y flujos de “modo degradado” en un entorno sandbox.
Los chequeos tradicionales de uptime no detectarán “disponible pero equivocado”. Supervisa:
Los operadores necesitan acciones predefinidas cuando ocurre una partición: cuándo congelar escrituras, cuándo hacer failover, cuándo degradar funciones, y cómo validar la seguridad de la re-fusión.
También planifica el comportamiento visible al usuario. Si eliges consistencia, el mensaje podría ser “No podemos confirmar tu actualización ahora—por favor reintenta.” Si eliges disponibilidad, sé explícito: “Tu actualización puede tardar unos minutos en aparecer en todos los dispositivos.” Un wording claro reduce la carga de soporte y preserva la confianza.
Cuando tomes una decisión de sistema, CAP es más útil como una auditoría rápida de “¿qué se rompe durante una partición?”—no como un debate teórico. Usa esta checklist antes de elegir una característica de base de datos, estrategia de cache o modo de replicación.
Pregúntate en este orden:
Si ocurre una partición, estás decidiendo qué de esto protegerás primero.
Evita un ajuste global como “somos un sistema AP”. En su lugar decide por:
Ejemplo: durante una partición, puedes bloquear escrituras a payments (favorecer consistencia) pero mantener lecturas de product_catalog disponibles con datos en caché.
Anota qué toleras, con ejemplos:
Si no puedes describir la inconsistencia en ejemplos claros, te costará probarla y explicar incidentes.
Temas siguientes que encajan bien con esta checklist: consenso (/blog/consensus-vs-cap), modelos de consistencia (/blog/consistency-models-explained), y SLOs/presupuestos de error (/blog/sre-slos-error-budgets).
CAP es un modelo mental para sistemas replicados bajo fallos de comunicación. Es más útil cuando la red es lenta, pierde paquetes o se divide, porque es entonces cuando los réplicas no pueden acordar de forma fiable y te ves obligado a elegir entre:
Te ayuda a convertir el típico “lo distribuido es difícil” en una decisión concreta de producto e ingeniería.
Un verdadero escenario CAP requiere ambas cosas:
Si tu sistema es de un único nodo, o no replicas estado, las compensaciones CAP no son el problema central.
Una partición es cualquier situación en la que partes de tu sistema no pueden comunicarse de forma fiable o dentro de los límites de tiempo requeridos—incluso si todas las máquinas siguen ejecutándose.
En la práctica, “partición” suele manifestarse como:
Desde la perspectiva de la aplicación, “demasiado lento” puede ser lo mismo que “caído”.
Consistencia (C) significa que las lecturas reflejan la última escritura reconocida desde cualquier lugar. Los usuarios lo experimentan como “lo cambié y todo el mundo lo ve”.
Disponibilidad (A) significa que cada petición recibe una respuesta exitosa (no necesariamente la más reciente). Los usuarios lo experimentan como “la app sigue funcionando”, quizá con datos obsoletos.
Durante una partición, normalmente no puedes garantizar ambas cosas simultáneamente para todas las operaciones.
Porque las particiones no son opcionales en sistemas distribuidos que abarcan máquinas, racks, zonas o regiones. Si replicas, debes definir comportamiento para cuando los nodos no puedan coordinarse.
“Tolerar particiones” suele significar: cuando la comunicación falla, el sistema aún tiene una forma definida de operar—o bien rechazando/pausando algunas acciones (favoreciendo consistencia) o bien sirviendo resultados aproximados (favoreciendo disponibilidad).
Si favoreces consistencia, normalmente:
Esto es habitual en movimientos de dinero, reservas de inventario y cambios de permisos—lugares donde equivocarse es peor que estar temporalmente inaccesible.
Si favoreces disponibilidad, normalmente:
Los usuarios ven menos errores duros, pero pueden ver datos obsoletos, efectos duplicados sin idempotencia, o conflictos que necesitan limpieza.
Puedes elegir distinto por endpoint/tipo de dato. Estrategias mixtas comunes incluyen:
Esto evita una etiqueta global “somos AP/CP” que rara vez se ajusta a las necesidades reales del producto.
Opciones útiles incluyen:
Valida creando condiciones donde la discrepancia sea visible:
Elige la garantía más débil que evite el “error” visible al usuario que no puedas tolerar.
También prepara runbooks y comunicaciones al usuario que reflejen el comportamiento elegido (fallar cerrado vs fallar abierto).