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?
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.

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
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
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.
¿Te gusta lo que lees?
Unete a otros ingenieros que reciben reflexiones sobre carrera, liderazgo y tecnologia cada semana.
Articulos relacionados
El ADN del software no era un concepto. Era 24 archivos.
Hace tres semanas defendí que el código se iba a volver desechable y lo importante sería el ADN del software. Me encerré a comprobar si esa idea era escribible de verdad. Lo que sale: 24 archivos, dos regeneraciones por menos de un euro cada una, un repo público, y bastante claridad sobre lo que el harness engineering aún no resuelve.
Cuando los LLMs generen miles de tokens por segundo, lo que importa no será el código
Si regenerar es más barato que mantener, la estrategia racional no es cuidar el código. Es hacer que sea desechable por diseño e invertir en lo que no es desechable. El futuro del ingeniero es escribir ADN, no código.
La disciplina no escala. La verificación necesita infraestructura.
La disciplina individual como sistema de calidad es un diseño frágil. Los tests escalaron porque se convirtieron en infraestructura. La verificación necesita hacer lo mismo.
