Aprende por qué las bases de datos distribuidas suelen relajar la consistencia para mantenerse disponibles durante fallos, cómo funcionan CAP y los quórums, y cuándo elegir cada enfoque.

Cuando una base de datos está repartida en varias máquinas (réplicas), ganas velocidad y resiliencia, pero también introduces periodos en los que esas máquinas no están perfectamente de acuerdo o no pueden comunicarse con fiabilidad.
Consistencia significa: después de una escritura exitosa, todo el mundo lee el mismo valor. Si actualizas el correo de tu perfil, la siguiente lectura—sin importar qué réplica responda—devuelve el nuevo correo.
En la práctica, los sistemas que priorizan la consistencia pueden retrasar o rechazar algunas peticiones durante fallos para evitar responder con respuestas en conflicto.
Disponibilidad significa: el sistema responde a cada petición, incluso si algunos servidores están caídos o desconectados. Puede que no obtengas los datos más recientes, pero obtienes una respuesta.
En la práctica, los sistemas que priorizan la disponibilidad pueden aceptar escrituras y servir lecturas incluso mientras las réplicas discrepan, y luego conciliar las diferencias más tarde.
Un intercambio significa que no puedes maximizar ambos objetivos al mismo tiempo en todos los escenarios de fallo. Si las réplicas no pueden coordinarse, la base de datos debe o bien:
El balance correcto depende de qué errores puedes tolerar: un breve corte o un corto periodo de datos equivocados/antiguos. La mayoría de sistemas reales elige un punto intermedio y hace explícito el intercambio.
Una base de datos es “distribuida” cuando almacena y sirve datos desde múltiples máquinas (nodos) que coordinan a través de una red. Para una aplicación, puede seguir pareciendo una única base de datos; pero en el fondo, las peticiones pueden ser atendidas por nodos distintos en lugares distintos.
La mayoría de bases de datos distribuidas replican datos: el mismo registro se almacena en varios nodos. Los equipos hacen esto para:
La replicación es poderosa, pero plantea inmediatamente una pregunta: si dos nodos tienen copia del mismo dato, ¿cómo garantizas que siempre estén de acuerdo?
En un único servidor, “caído” suele ser obvio: la máquina está arriba o no lo está. En un sistema distribuido, el fallo suele ser parcial. Un nodo puede estar vivo pero lento. Un enlace de red puede perder paquetes. Una rack entera puede perder conectividad mientras el resto del clúster sigue funcionando.
Esto importa porque los nodos no pueden saber al instante si otro nodo está realmente caído, temporalmente inalcanzable o simplemente retrasado. Mientras esperan averiguarlo, deben decidir qué hacer con las lecturas y escrituras entrantes.
Con un servidor, hay una única fuente de verdad: cada lectura ve la última escritura exitosa.
Con múltiples nodos, “lo último” depende de la coordinación. Si una escritura tiene éxito en el nodo A pero el nodo B no puede alcanzarse, ¿debe la base de datos:
Esa tensión—hecha real por redes imperfectas—es por qué la distribución cambia las reglas.
Una partición de red es una ruptura en la comunicación entre nodos que deberían funcionar como una sola base de datos. Los nodos pueden seguir ejecutándose y estar saludables, pero no pueden intercambiar mensajes de forma fiable—debido a un switch fallido, un enlace sobrecargado, un cambio de enrutamiento, una regla de firewall mal configurada o incluso un “vecino ruidoso” en una red en la nube.
Una vez que un sistema se extiende por múltiples máquinas (a menudo entre racks, zonas o regiones), ya no controlas cada salto entre ellas. Las redes pierden paquetes, introducen retardos y a veces se dividen en “islas”. A pequeña escala estos eventos son raros; a gran escala son rutinarios. Incluso una breve interrupción es suficiente para importar, porque las bases de datos necesitan coordinación constante para ponerse de acuerdo sobre lo que ocurrió.
Durante una partición, ambos lados siguen recibiendo peticiones. Si los usuarios pueden escribir en ambos lados, cada lado puede aceptar actualizaciones que el otro no ve.
Ejemplo: el nodo A actualiza la dirección de un usuario a “Calle Nueva”. Al mismo tiempo, el nodo B la actualiza a “Calle Vieja Apt 2”. Cada lado cree que su escritura es la más reciente—porque no tiene forma de comparar notas en tiempo real.
Las particiones no aparecen como mensajes de error ordenados; aparecen como comportamientos confusos:
Este es el punto de presión que fuerza una elección: cuando la red no puede garantizar comunicación, una base de datos distribuida debe decidir si prioriza ser consistente o estar disponible.
CAP es una forma compacta de describir lo que ocurre cuando una base de datos se distribuye entre varias máquinas.
Cuando no hay partición, muchos sistemas pueden parecer tanto consistentes como disponibles.
Cuando sí hay una partición, debes elegir qué priorizar:
balance = 100 en el Servidor A.balance = 80.CAP no significa “elige solo dos” como regla permanente. Significa durante una partición, no puedes garantizar tanto Consistencia como Disponibilidad al mismo tiempo. Fuera de las particiones, a menudo puedes acercarte mucho a ambas—hasta que la red se porta mal.
Elegir consistencia significa que la base de datos prioriza “todos ven la misma verdad” sobre “responder siempre”. En la práctica, esto suele apuntar a consistencia fuerte, a menudo descrita como comportamiento linearizable: una vez que una escritura es reconocida, cualquier lectura posterior (desde cualquier lugar) devuelve ese valor, como si hubiese una única copia actualizada.
Cuando la red se divide y las réplicas no pueden comunicarse de forma fiable, un sistema fuertemente consistente no puede aceptar de forma segura actualizaciones independientes en ambos lados. Para proteger la corrección, típicamente:
Desde la perspectiva del usuario, esto puede parecer una caída aunque algunas máquinas sigan funcionando.
El beneficio principal es razonamiento más simple. El código de la aplicación puede comportarse como si hablara con una única base de datos, no con varias réplicas que podrían discrepar. Esto reduce momentos “raros” como:
También obtienes modelos mentales más limpios para auditoría, facturación y cualquier cosa que deba ser correcta a la primera.
La consistencia tiene costes reales:
Si tu producto no puede tolerar peticiones fallidas durante cortes parciales, la consistencia fuerte puede resultar cara—aunque sea la opción correcta para la corrección.
Elegir disponibilidad significa optimizar por una promesa simple: el sistema responde, incluso cuando partes de la infraestructura están poco saludables. En la práctica, “alta disponibilidad” no es “sin errores nunca”: es que la mayoría de las peticiones aún obtienen respuesta durante fallos de nodo, réplicas sobrecargadas o enlaces rotos.
Cuando la red se divide, las réplicas no pueden hablar de forma fiable entre sí. Una base de datos que prioriza la disponibilidad típicamente sigue atendiendo tráfico desde el lado alcanzable:
Esto mantiene las aplicaciones en marcha, pero significa que distintas réplicas pueden aceptar “verdades” temporales.
Obtienes mejor tiempo de actividad: los usuarios aún pueden navegar, añadir items al carrito, publicar comentarios o registrar eventos aunque una región esté aislada.
También logras una experiencia de usuario más suave bajo estrés. En lugar de timeouts, tu app puede continuar con comportamiento razonable (“tu actualización está guardada”) y sincronizar después. Para muchas cargas de trabajo de consumo y analítica, ese intercambio merece la pena.
El precio es que la base de datos puede devolver lecturas obsoletas. Un usuario puede actualizar un perfil en una réplica y, acto seguido, leer desde otra y ver el valor antiguo.
También arriesgas conflictos de escritura. Dos usuarios (o el mismo usuario en dos ubicaciones) pueden actualizar el mismo registro en distintos lados de la partición. Cuando la partición sana, el sistema debe reconciliar historiales divergentes. Según las reglas, una escritura puede “ganar”, los campos pueden fusionarse o el conflicto puede requerir lógica de aplicación.
El diseño orientado a disponibilidad acepta el desacuerdo temporal para que el producto siga respondiendo—y luego invierte en cómo detectar y reparar la discrepancia.
Los quórums son una técnica práctica de “votación” que muchas bases de datos replicadas usan para equilibrar consistencia y disponibilidad. En lugar de confiar en una réplica, el sistema pide a suficientes réplicas que estén de acuerdo.
A menudo verás quórums descritos con tres números:
Una regla práctica es: si R + W > N, entonces cada lectura se solapa con la última escritura exitosa en al menos una réplica, lo que reduce la posibilidad de leer datos obsoletos.
Si tienes N=3 réplicas:
Algunos sistemas usan W=3 (todas las réplicas) para mayor consistencia, pero eso puede causar más fallos de escritura cuando cualquier réplica está lenta o caída.
Los quórums no eliminan los problemas de partición: definen quién puede avanzar. Si la red se divide 2–1, el lado con 2 réplicas aún puede satisfacer R=2 y W=2, mientras que la réplica aislada no puede. Eso reduce actualizaciones en conflicto, pero significa que algunos clientes verán errores o timeouts.
Los quórums suelen implicar mayor latencia (más nodos a contactar), mayor coste (más tráfico entre nodos) y comportamientos de fallo más matizados (los timeouts pueden parecer indisponibilidad). El beneficio es un término medio ajustable: puedes girar R y W hacia lecturas más frescas o más éxito en escrituras según lo que importe.
Consistencia eventual significa que las réplicas pueden estar temporalmente desincronizadas, siempre que converjan al mismo valor más adelante.
Piensa en una cadena de cafeterías que actualiza un cartel compartido de “agotado” para un pastel. Una tienda lo marca como agotado, pero la actualización llega a las demás tiendas unos minutos después. Durante ese intervalo, otra tienda puede aún mostrar “disponible” y vender el último. El sistema no está “roto”: las actualizaciones simplemente se están poniendo al día.
Cuando los datos aún se propagan, los clientes pueden observar comportamientos que parecen sorprendentes:
Los sistemas de consistencia eventual suelen añadir mecanismos en segundo plano para reducir las ventanas de inconsistencia:
Es adecuada cuando la disponibilidad importa más que estar perfectamente al día: feeds de actividad, contadores de vista, recomendaciones, perfiles en caché, logs/telemetría y otros datos no críticos donde “correcto en un momento” es aceptable.
Cuando una base de datos acepta escrituras en varias réplicas, puede acabar con conflictos: dos (o más) actualizaciones al mismo ítem que ocurrieron independientemente en distintas réplicas antes de que pudieran sincronizarse.
Un ejemplo clásico es un usuario que actualiza su dirección de envío en un dispositivo mientras cambia su número de teléfono en otro. Si cada actualización llega a una réplica distinta durante un desconecte temporal, el sistema debe decidir cuál es el registro “verdadero” cuando las réplicas intercambian datos otra vez.
Muchos sistemas empiezan con última escritura gana: la actualización con la marca de tiempo más reciente sobrescribe las demás.
Es atractivo porque es fácil de implementar y rápido de calcular. La desventaja es que puede perder datos en silencio. Si gana lo “más nuevo”, una actualización más antigua pero importante se descarta—incluso si las dos escribieron campos distintos.
También asume que los relojes son fiables. La deriva de reloj entre máquinas (o clientes) puede hacer que la actualización “incorrecta” gane.
Un manejo más seguro de conflictos suele requerir rastrear historial causal.
A nivel conceptual, los vectores de versión (y variantes más simples) adjuntan un pequeño metadato a cada registro que resume “qué réplica ha visto qué actualizaciones”. Cuando las réplicas intercambian versiones, la base de datos puede detectar si una versión incluye a otra (sin conflicto) o si han divergido (conflicto que necesita resolución).
Algunos sistemas usan relojes lógicos (por ejemplo, relojes de Lamport) o relojes lógicos híbridos para reducir la dependencia del tiempo de pared manteniendo una pista de orden.
Una vez detectado el conflicto, hay opciones:
La mejor aproximación depende de qué significa “correcto” para tus datos—a veces perder una escritura es aceptable, y a veces es un error crítico para el negocio.
Escoger una postura de consistencia/disponibilidad no es un debate filosófico: es una decisión de producto. Empieza preguntándote: ¿cuál es el coste de estar equivocado por un momento, y cuál es el coste de decir “vuelve a intentarlo más tarde”?
Algunos dominios necesitan una respuesta única y autorizada en el momento de la escritura porque “casi correcto” sigue siendo incorrecto:
Si el impacto de un desfase temporal es bajo o reversible, normalmente puedes inclinarte por mayor disponibilidad.
Muchas experiencias de usuario funcionan con lecturas algo antiguas:
Sé explícito sobre cuánto atraso está bien: segundos, minutos u horas. Ese presupuesto de tiempo guía tus elecciones de replicación y quórum.
Cuando las réplicas no pueden ponerse de acuerdo, normalmente acabas con uno de tres resultados de UX:
Elige la opción menos dañina por característica, no de forma global.
Inclínate por C (consistencia) si: resultados equivocados generan riesgo financiero/legal, problemas de seguridad o acciones irreversibles.
Inclínate por A (disponibilidad) si: los usuarios valoran la capacidad de respuesta, los datos obsoletos son tolerables y los conflictos pueden resolverse con seguridad después.
En caso de duda, divide el sistema: mantén registros críticos con consistencia fuerte y deja que vistas derivadas (feeds, caches, analítica) optimicen para disponibilidad.
Rara vez tienes que elegir una única “configuración de consistencia” para todo el sistema. Muchas bases de datos distribuidas modernas permiten elegir la consistencia por operación, y las aplicaciones inteligentes aprovechan eso para mantener la experiencia de usuario sin pretender que el intercambio no existe.
Trata la consistencia como un dial que giras según lo que el usuario está haciendo:
Así evitas pagar el coste de la máxima consistencia para todo, protegiendo solo las operaciones que realmente lo necesitan.
Un patrón común es fuerte para escrituras, más débil para lecturas:
En algunos casos funciona al revés: escrituras rápidas (encoladas/eventuales) más lecturas fuertes al confirmar un resultado (“¿Se ha realizado mi pedido?”).
Cuando las redes vacilan, los clientes reintentan. Haz que los reintentos sean seguros con idempotency keys de modo que “enviar pedido” ejecutado dos veces no cree dos pedidos. Guarda y reutiliza el primer resultado si la misma clave aparece otra vez.
Para acciones en varios pasos entre servicios, usa una saga: cada paso tiene una acción compensatoria correspondiente (reembolso, liberar reserva, cancelar envío). Esto mantiene el sistema recuperable incluso cuando partes discrepan o fallan temporalmente.
No puedes gestionar el intercambio de consistencia/disponibilidad si no puedes verlo. Los problemas en producción suelen parecer “fallos aleatorios” hasta que añades las medidas y pruebas adecuadas.
Empieza con un conjunto pequeño de métricas que se mapeen directamente al impacto usuario:
Si puedes, etiqueta métricas por modo de consistencia (quórum vs local) y por región/zona para detectar dónde diverge el comportamiento.
No esperes a que ocurra el fallo real. En staging, ejecuta experimentos de caos que simulen:
Verifica no solo “el sistema sigue funcionando”, sino qué garantías se mantienen: ¿las lecturas siguen frescas, las escrituras bloquean, los clientes obtienen errores claros?
Añade alertas para:
Por último, documenta explícitamente las garantías: qué promete tu sistema durante la operación normal y durante particiones, y forma a producto y soporte en qué pueden ver los usuarios y cómo responder.
Si exploras estos intercambios en un producto nuevo, ayuda validar las suposiciones pronto—especialmente sobre modos de fallo, comportamiento de reintentos y cómo se ve lo “obsoleto” en la UI.
Un enfoque práctico es prototipar una versión pequeña del flujo (ruta de escritura, ruta de lectura, reintento/idempotencia y un job de reconciliación) antes de comprometerte con una arquitectura completa. Con Koder.ai, los equipos pueden poner en marcha apps web y backends mediante un flujo guiado por chat, iterar rápido en modelos de datos y APIs, y probar distintos patrones de consistencia (por ejemplo, escrituras estrictas + lecturas relajadas) sin la sobrecarga de un pipeline de construcción tradicional. Cuando el prototipo se ajusta al comportamiento deseado, puedes exportar el código fuente y evolucionarlo hacia producción.
En una base de datos replicada, los mismos datos residen en varias máquinas. Esto aumenta la resistencia y puede reducir la latencia, pero introduce problemas de coordinación: los nodos pueden estar lentos, inalcanzables o separados por la red, por lo que no siempre pueden ponerse de acuerdo al instante sobre la última escritura.
Consistencia significa: después de una escritura exitosa, cualquier lectura posterior devuelve ese mismo valor—sin importar qué réplica la sirva. En la práctica, los sistemas suelen imponer esto retrasando o rechazando lecturas/escrituras hasta que suficientes réplicas (o un líder) confirmen la actualización.
Disponibilidad significa que el sistema devuelve una respuesta no errónea a cada solicitud, incluso cuando algunos nodos están caídos o no pueden comunicarse. La respuesta puede estar obsoleta, parcial o basada en conocimiento local, pero el sistema evita bloquear a los usuarios durante fallos.
Una partición de red es una ruptura en la comunicación entre nodos que deberían actuar como un único sistema. Los nodos pueden seguir funcionando, pero los mensajes no cruzan de forma fiable, lo que fuerza a la base de datos a elegir entre:
Durante una partición, ambos lados pueden aceptar actualizaciones que no pueden compartir de inmediato. Eso puede provocar:
Estos son síntomas visibles para el usuario de que las réplicas no pueden coordinarse temporalmente.
No significa “elige dos para siempre”. Significa que cuando ocurre una partición, no puedes garantizar simultáneamente:
Fuera de las particiones, muchos sistemas pueden aparentar ofrecer ambas cosas la mayor parte del tiempo, hasta que la red falla.
Los quórums usan votación entre réplicas:
Una guía común es R + W > N para reducir lecturas obsoletas. Los quórums no eliminan las particiones; definen qué lado puede avanzar (por ejemplo, el que aún tiene mayoría).
La consistencia eventual permite que las réplicas estén temporalmente fuera de sincronía siempre que converjan después. Anomalías comunes incluyen:
Los sistemas mitigan esto con , y reconciliación periódica ().
Los conflictos ocurren cuando diferentes réplicas aceptan escrituras distintas al mismo ítem durante un desconecte. Estrategias de resolución incluyen:
Elige según qué signifique “correcto” para tus datos.
Decídelo según el riesgo del negocio y el modo de fallo que los usuarios puedan tolerar:
Patrones prácticos: niveles de consistencia por operación, reintentos seguros con , y con compensación para flujos multi-paso.