10 min de lectura

Emilio Carrión

No elijas tu base de datos global desde un diagrama

Tener usuarios en dos continentes no significa necesitar una base de datos globalmente consistente. Antes de elegir entre Spanner, DynamoDB o Aurora, la pregunta es otra: ¿qué dato te falta para decidir bien?

arquitecturasistemas distribuidosiotdecisiones técnicas

Hace poco, el equipo de Kode me invitó a sentarme con ellos una tarde a pensar su arquitectura de datos. Si no los conoces: la startup de hardware detrás de Kode Dot, un dispositivo de bolsillo all-in-one para makers con su propio sistema operativo, kodeOS, y su catálogo de apps, todo open source. Y que ya opera en Estados Unidos y en Europa: pocas startups de hardware llegan tan pronto a gestionar una flota en dos continentes.

El dispositivo de Kode sobre una mesa de trabajo, rodeado de sensores, cables y componentes electrónicos

Encima de la mesa había una pregunta que suena a las que importan: ¿Spanner? ¿Aurora multi-región? ¿DynamoDB Global Tables? ¿Bigtable? Cuatro nombres potentes, un montón de horas leyendo documentación de vendors, y una flota de dispositivos repartida en dos continentes que hay que servir bien.

Estuvimos un buen rato dándole vueltas. Y que conste que no era una pregunta lanzada a la ligera: nos sentamos a repasar juntos las opciones, a acotarlas y a leer bien los trade-offs de cada una. Pero la conversación más útil que tuvimos no fue elegir uno de los cuatro. Fue darnos cuenta de que todavía no teníamos los datos para elegir ninguno.

Eso es lo que quiero contarte hoy.

El impulso de "somos globales, montemos lo global"

Hay una trampa muy fácil de pisar cuando tu producto cruza fronteras: confundir "tengo usuarios en dos continentes" con "necesito una base de datos globalmente consistente".

Son cosas distintas. La primera es un hecho de tu negocio. La segunda es una decisión de ingeniería carísima, y no solo en la factura. Una pieza tipo Spanner te cuesta dinero, sí, pero te cuesta sobre todo en coste operativo y cognitivo: un modelo de consistencia que tu equipo tiene que entender, monitorizar y depurar cuando algo va mal a las tres de la mañana.

Y ese impulso tiene letra pequeña: te lleva a elegir el modelo más caro y más pesado sin un solo dato de lo que tu producto necesita en realidad. Decides desde la intuición de "vamos a ir a por todas" en vez de desde lo que te diría medir.

Te lo digo como alguien a quien le ha pasado. Me he enamorado más de una vez de una pieza de infraestructura por el problema espectacular que prometía resolver, no por el problema que yo tenía delante. No es agradable de admitir, pero es así.

Cada vendor te vende su peor caso, no el tuyo

Spanner existe porque Google tenía un problema de consistencia fuerte a escala planetaria. DynamoDB Global Tables existe para multi-master con replicación eventual. Bigtable para throughput brutal de series temporales. Aurora Global Database para lecturas locales y recuperación ante desastres entre regiones, manteniendo un único primario de escritura. Todas son piezas excelentes resolviendo problemas reales.

Pero esos problemas son los suyos, o los de sus mayores clientes. La página de marketing describe el caso límite que justifica la herramienta, no tu caso. Y si eliges leyendo la página de marketing, acabas dimensionando tu arquitectura para un problema que probablemente no tienes.

La pregunta no es "¿cuál de estas es mejor?". Es "¿cuál de estos problemas es el mío?". Y para responder eso necesitas mirar tus propios datos.

La pregunta que casi nadie hace: ¿tus datos particionan solos?

En una flota de dispositivos IoT, los datos casi siempre particionan de forma natural por device y por región. Un dispositivo en Texas y uno en Valencia rara vez necesitan una transacción consistente entre sí. Cada uno reporta su telemetría, recibe sus comandos, guarda su estado.

Si tus datos ya están naturalmente particionados, una parte enorme del valor de una base de datos global desaparece. La consistencia fuerte global resuelve el problema de coordinar escrituras que compiten por el mismo dato desde dos sitios a la vez. Si eso casi nunca pasa en tu dominio, estás pagando por una garantía que no usas.

No quiero venderte que esto sea siempre así. Hay productos donde el dato sí es global y compartido (un saldo, un inventario único, un documento colaborativo). Pero merece la pena mirarlo bien antes de darlo por hecho.

No hay una respuesta, hay un perfil por caso de uso

Y aquí, para mí, está el quid: no tienes un problema de base de datos, tienes varios, y cada uno aguanta cosas distintas.

Piénsalo por casos de uso. El registro de un dispositivo, el catálogo de apps de su sistema operativo, la telemetría que sube, los comandos o las actualizaciones OTA que bajan. Cada uno con su propia tolerancia a la latencia y a la consistencia.

La telemetría tolera replicación eventual y un par de cientos de milisegundos sin que a nadie le tiemble el pulso. Un comando interactivo, donde el usuario toca algo y espera respuesta, no tolera lo mismo. Meter todo eso en una única decisión global ("¿qué base de datos usamos?") es justo el error: estás promediando requisitos que no se parecen en nada.

Cada flujo aguanta cosas distintas

TOLERA EVENTUALEXIGE INMEDIATOTelemetríaaguanta cientos de ms y replicación eventualActualizaciones OTAbajan en background, se pueden reintentarRegistro y catálogose lee mucho, cambia pocoComando interactivoel usuario toca algo y espera respuesta
Una única decisión global (“¿qué base de datos usamos?”) promedia requisitos que no se parecen en nada. La pregunta mejor: qué necesita cada flujo.

Cuando separas por caso de uso, la pregunta deja de ser "Spanner o DynamoDB" y pasa a ser "qué necesita cada flujo". Que es una pregunta mucho mejor.

Una región, pero instrumentada de verdad

La propuesta que salió de la conversación con Kode fue empezar por una sola región. Hace falta más criterio para defender ese plan teniendo ambición global que para firmar el presupuesto de Spanner, y ellos lo entendieron al vuelo. Pero quiero ser preciso con lo que eso significa, porque "empezar por una región" se confunde con "hacer un MVP de juguete y ya veremos".

No es eso. Es montar una región bien, e instrumentarla para medir lo que importa: latencias p50, p95 y p99 por cada caso de uso, vistas desde clientes reales en los dos continentes. Quieres saber qué le pasa a un dispositivo en Europa hablando con un backend en Estados Unidos, y saberlo por los números que ves, no por lo que crees que va a pasar.

Lo que descubres así no lo sabías dibujando. Igual resulta que la telemetría aguanta de sobra el salto transatlántico y el único flujo que duele es el comando interactivo. O al revés. El diagrama no te lo va a decir.

Y esto no es teoría que me haya inventado para el post. En Mercadona Tech, donde trabajo como Staff Engineer, procesamos del orden de 25.000 pedidos al día, y las decisiones de arquitectura que de verdad cambiaron algo no salieron de una pizarra bonita. Salieron de mirar números en producción y de descubrir que el cuello de botella estaba donde nadie lo habría puesto en el diagrama inicial.

Por qué la respuesta suele ser un híbrido

Con esos datos, la arquitectura razonable casi nunca es "una pieza mágica para todo". Es un híbrido: broker MQTT regional para lo local y caliente, un store particionado donde los datos viven por región, replicación eventual para lo global y frío que solo necesitas para agregados y analítica.

Y el catálogo de apps es el caso contrario al store particionado: se escribe en un sitio y se lee en todas partes. Una réplica de lectura por región te da latencia local sin pelearte con la consistencia, porque un catálogo que se actualiza cada semana aguanta sin despeinarse que sus réplicas vayan unos segundos por detrás.

El híbrido: regional para lo caliente, eventual para lo frío

REGIÓN EUROPAdispositivosBroker MQTTlo local y calienteStore regionalel dato vive aquíRéplica del catálogolecturas localesRGPD: residencia de datosREGIÓN EE. UU.dispositivosBroker MQTTlo local y calienteStore regionalel dato vive aquíRéplica del catálogolecturas localesCatálogo (primario)se escribe en un sitioreplicación eventualGlobal y fríoagregados y analítica
Híbrido no es no atreverse a elegir: es quitar complejidad donde no aporta y ponerla donde el usuario nota la diferencia.

Híbrido suena a "no se atreven a elegir". Es lo contrario: es quitar complejidad donde no aporta y ponerla donde el usuario nota la diferencia.

Lo regional tampoco es gratis

Y ojo, que lo regional que acabo de defender tampoco sale gratis. En cuanto te pones a dibujar un store particionado por región, con una instancia por región en vez de una base global, aparecen sus propios problemas.

El primero es el enrutado: cada vez que llega una petición, alguien tiene que saber a qué región pertenece ese usuario para mandarla a la instancia correcta. Eso es una pieza más que mantener, y una más que puede fallar.

El segundo es más feo: ¿qué pasa cuando un usuario cambia de país? Su dato ya no debería vivir donde vive. Tienes que migrarlo de una región a otra sin perder nada ni dejarlo a medias, y resolver qué ocurre durante la ventana en la que está moviéndose. No es imposible, pero es trabajo real, y es justo el tipo de complejidad que no ves en el diagrama y sí sufres en producción.

Lo cuento porque casi nunca sale en estas conversaciones. No hay opción gratis. Hay costes que ves venir y decides pagar, y costes que te encuentras tarde, cuando ya no toca. Y otra vez, lo que marca la diferencia es cuánto habías medido antes de elegir.

El camino de migración es lo que separa simple bien hecho de simple ingenuo

Y alguien dirá: "claro, empiezas simple y luego te quedas atascado con una arquitectura que no escala". Es la objeción correcta, y hay que tomársela en serio.

La trampa de empezar simple es real. La diferencia entre hacerlo bien y hacerlo ingenuamente es una sola cosa: tener escrito de antemano el trigger de migración. Qué métrica concreta, qué umbral, qué movimiento dispara el salto a multi-región. Por ejemplo: "si el p95 del comando interactivo en Europa pasa de X durante Y tiempo sostenido, movemos ese flujo concreto a una segunda región". Y ese acuerdo no puede vivir en la memoria de nadie: escríbelo en un ADR (aquí tienes un generador si no tienes plantilla a mano).

Cuando tienes eso escrito, empezar por una región no es deuda técnica. Es una opción que ejerces el día que los datos lo pidan, sobre el subsistema concreto que lo pida, y no sobre todo a la vez.

Y hay otro lado, que también hay que poner sobre la mesa: hacerlo todo bien desde el principio asume que ya sabes qué es "bien". Migrar un subsistema concreto cuando tienes datos suele salir más barato que operar, pagar y mantener durante dos años una arquitectura global que igual no necesitabas. Pero no siempre. Si sabes desde el minuto cero que vas a necesitar lo pesado, forzar el "empieza simple" sería igual de dogmático que lo contrario.

Lo que me llevo

No tengo una regla universal que darte. Desconfía de quien te la dé.

Lo que sí tengo es una pregunta que hago siempre, en Mercadona Tech y en conversaciones como la de Kode, antes de tomar una decisión de arquitectura grande: ¿qué dato me falta para decidir esto bien, y cuánto cuesta conseguirlo? Casi siempre el dato es muchísimo más barato que la decisión. Una región instrumentada durante unas semanas cuesta una fracción de lo que cuesta equivocarse de base de datos global y vivir con ello.

Hoy cualquier LLM te suelta las diferencias entre Spanner y DynamoDB en diez segundos. Eso ha dejado de ser lo escaso. Lo escaso es saber qué pregunta hacer antes de elegir, y tener la disciplina de medir en vez de suponer. El código, y la infraestructura, son un medio. Lo que estás diseñando es el producto.

El diagrama no conoce tu latencia. Tus usuarios sí.

Pregunta para ti: ¿cuántas de las decisiones de arquitectura grandes de tu equipo se tomaron mirando números reales, y cuántas se tomaron mirando un diagrama y la página de un vendor? No lo pregunto con juicio. Lo pregunto porque creo que la respuesta dice mucho sobre dónde está el verdadero coste.

Newsletter Semanal

¿Te gusta lo que lees?

Unete a otros ingenieros que reciben reflexiones sobre carrera, liderazgo y tecnologia cada semana.

Compartir:
Emilio Carrión
Sobre el autor

Emilio Carrión

Staff Engineer en Mercadona Tech. Ayudo a ingenieros a pensar en producto y a construir sistemas que escalan. Obsesionado con la arquitectura evolutiva y los equipos de alto rendimiento.