Diseñar para la velocidad: argumentos a favor de la ingesta de eventos sin esquema

SchemaBridge Team · 2025-12-08 · Event Ingestion, JSON, DX

Velocidad frente a tipos estrictos en sistemas orientados a eventos. Por qué elegimos JSON en bruto en lugar de definiciones de tipos estrictas.

La paradoja del esquema: ¿amigo o enemigo?

En el software empresarial tradicional, los esquemas estrictos (SQL, Protobuf, WSDL) son la base de la fiabilidad. El contrato es sencillo: yo defino la forma de los datos, tú te ajustas a ella y el compilador garantiza que nada se caiga. Este enfoque nos ha servido bien durante décadas en entornos controlados en los que somos dueños de ambos extremos de la tubería. Ofrece seguridad en tiempo de compilación, una serialización binaria eficiente y una «fuente de verdad» clara para los desarrolladores.

Pero en un entorno de integración moderno y de alta velocidad —donde los proveedores SaaS cambian sus payloads cada semana, los ERP heredados emiten CSV «flexibles» y los microservicios internos nacen y se retiran cada mes—, los esquemas rígidos se convierten en una camisa de fuerza. Aportan seguridad a costa de la inercia. Cuando el mundo a tu alrededor es fluido, un contrato rígido no es un cimiento: es un punto de fallo. La paradoja del esquema es esta: cuanto más intentas proteger tu sistema con tipos estrictos, más frágil lo vuelves cuando el mundo exterior cambia.

La evolución histórica: de COBOL a JSON

Para entender la demanda de sistemas sin esquema, hay que mirar la evolución del intercambio de datos. En los primeros tiempos de los mainframes, los datos se almacenaban en registros de longitud fija (los COPYBOOK de COBOL). Si querías añadir un campo, tenías que recompilar todos los programas que leían ese registro. Era el esquema rígido por excelencia. Era la era de la «mentalidad de una sola máquina», en la que el almacenamiento era tan caro que cada byte debía quedar contabilizado en una posición fija. No había espacio para la jerarquía, ni para la opcionalidad, y desde luego tampoco para la evolución. Cada carácter de un registro era un recurso precioso, y cualquier cambio era un terremoto que requería semanas de planificación y pruebas.

En los años 80 y 90 avanzamos hacia las bases de datos relacionales y SQL. Fue un salto enorme, porque introdujo el concepto de relaciones estructuradas. Pero también introdujo la migración de base de datos. Añadir una columna significaba tiempo de inactividad, tablas bloqueadas y una coordinación cuidadosa entre DBA y desarrolladores. El esquema seguía siendo un muro que los desarrolladores debían escalar cada vez que querían innovar. Incluso con el auge de ORM como Hibernate, la rigidez subyacente de la estructura de tablas siguió siendo el árbitro final de lo posible.

Después llegaron XML y SOAP a finales de los 90. Introdujeron el concepto de «etiquetas», que permitía cierta flexibilidad. Podías añadir una etiqueta XML sin romper necesariamente el parser. Sin embargo, la industria añadió enseguida XSD (XML Schema Definition) y WSDL, que devolvieron la rigidez. Pasamos años peleándonos con namespaces y complejos buses de servicios empresariales que rechazaban un mensaje si un solo carácter estaba fuera de lugar. Fue la «Edad Oscura del XML», en la que la sobrecarga del esquema consumía más ancho de banda que los propios datos.

Hoy tenemos JSON y REST. JSON es flexible por naturaleza. No es más que un mapa de claves y valores. Aun así, nuestros instintos de ingeniería nos empujan a envolver esa flexibilidad en tipos estrictos (interfaces de TypeScript, DTO de Java, esquemas Avro). Intentamos imponer la rigidez de los mainframes de los años 70 a los eventos en la nube de los años 2020. ¿Por qué? Porque tememos a lo desconocido. Tememos que un campo ausente tumbe nuestro servicio. Pero, como veremos, ese miedo se está abordando con las herramientas equivocadas.

El análisis financiero: el «impuesto oculto» del mantenimiento de integraciones

Cuantifiquemos el coste de la rigidez de los esquemas. En una organización de ingeniería típica, de tamaño medio a grande, el mantenimiento de integraciones es una «crisis silenciosa». No aparece como partida en el balance, pero supone un lastre enorme para la productividad.

Las cuentas del mantenimiento

El patrón es fácil de ver en cuanto lo buscas. Una organización con una amplia cartera de integraciones SaaS externas verá a los proveedores cambiar sus payloads con regularidad, y cada cambio que rompe un parser estricto desencadena el mismo ciclo: detección, actualización de DTO/esquemas, pruebas y un despliegue por CI/CD. Unas pocas horas por cada rotura, multiplicadas por muchas roturas al año, suman un drenaje sustancial y recurrente del tiempo de los ingenieros sénior.

Pero el coste real es el coste de oportunidad. Mientras tus ingenieros sénior actualizan DTO para el último cambio de Stripe, no están construyendo la nueva funcionalidad de detección automática de fraude que hace avanzar el negocio. Con el tiempo, este impuesto se acumula en una pérdida acumulada de velocidad que puede dejar a una empresa muy por detrás de competidores más ágiles.

La filosofía de la fluidez de datos: schema-on-read

En SchemaBridge defendemos un cambio de mentalidad fundamental: schema-on-read.

En lugar de validar los datos en el momento de su entrada (schema-on-write), primero ingerimos la verdad en bruto y jerárquica del evento. El payload JSON se persiste con la ejecución (run) exactamente tal como llegó, sin un esquema declarado de antemano. Solo aplicamos un esquema —o, más exactamente, una transformación— en el momento en que un proceso de negocio concreto necesita los datos.

Por qué gana la fluidez de datos

1. Ingesta sin intervención: puedes empezar a recibir eventos de un nuevo proveedor en segundos. Apunta el webhook del proveedor a un entry point de SchemaBridge (atendido por la capa de ingesta) y cada evento JSON inicia de inmediato una ejecución registrada. Qué significan los datos lo puedes averiguar después.

2. Un seguro frente a lo desconocido: si un proveedor añade hoy un campo que no necesitas, igualmente queda capturado en el JSON en bruto. Los payloads en bruto se conservan durante la ventana de retención de tu plan, así que si unas semanas después te das cuenta de que sí necesitas ese campo, la entrada en bruto sigue ahí: puedes reproducir ejecuciones individuales (o volver a enviar sus payloads) a través de un mapeo actualizado en lugar de pedirle datos antiguos al proveedor.

3. Evolución desacoplada: tu capa de ingesta y tu capa de transformación pueden evolucionar a velocidades distintas. Puedes actualizar tu lógica de negocio muchas veces al día sin tocar nunca tus entry points.

El argumento matemático a favor de la vinculación tardía

En informática, la vinculación tardía (late-binding) consiste en retrasar la resolución de una identidad o un tipo hasta el momento de la ejecución. Es lo que hace que lenguajes dinámicos como Ruby o Python sean tan potentes para ciertas tareas.

Schema-on-read es vinculación tardía aplicada a tu infraestructura de datos. Al retrasar el mapeo, pasas de un grafo rígido (donde cada cambio exige una reconstrucción completa) a un camino flexible (que puede adaptarse al terreno a medida que avanza).

Matemáticamente, el número de mapeos posibles entre $N$ productores y $M$ consumidores es $N \times M$. Si todos los productores y consumidores deben acordar un esquema estricto, tienes un problema de coordinación enorme. Si usas un puente sin esquema con vinculación tardía, reduces el problema a $N + M$ mapeos, cada uno local e independiente. Así se logra una verdadera escala horizontal de ingeniería.

JSONata: clase magistral de procesamiento funcional de eventos

Para que schema-on-read sea práctico, necesitas un lenguaje diseñado para el descubrimiento. Elegimos JSONata. JSONata no es solo un lenguaje de consulta; es un motor de transformación funcional que opera directamente sobre la jerarquía JSON en bruto.

Anatomía de una expresión JSONata

Considera un payload de un ERP heredado que devuelve una lista de pedidos. Cada pedido tiene una estructura compleja y anidada. Quieres extraer todos los números de pieza de los pedidos cuyo importe supera los 500 $ y que están actualmente en el estado 'SHIPPING'.

El código tradicional (Javascript):

const parts = payload.orders
  .filter(o => o.total > 500 && o.status === 'SHIPPING')
  .flatMap(o => o.items)
  .map(i => i.partNumber);

Este código es frágil. Si orders es null, o si falta items en algún pedido, se cae.

La maestría de JSONata:

orders[total > 500][status = 'SHIPPING'].items.partNumber

Esta expresión es tolerante a rutas. Un pedido sin items simplemente no aporta nada, y un payload sin ningún orders se resuelve en nada en lugar de en un fallo por puntero nulo. «Descubre» los datos en lugar de «presuponerlos».

Dos salvedades honestas. Primera: JSONata no hace magia con los tipos; si un proveedor empieza a enviar "total": "600" como cadena, la comparación lanza un error en lugar de adivinar. Segunda: en SchemaBridge, un mapeo que no produce ninguna salida hace fallar el paso en lugar de pasar un valor vacío aguas abajo. Es deliberado: un mapeo que de repente no coincide con nada casi siempre indica que la forma de los datos aguas arriba ha cambiado, y quieres que eso se note.

Patrón avanzado: selección profunda de descendientes

Una de las funciones más potentes de JSONata es el operador de descendientes **. Permite encontrar cualquier clave, esté donde esté en la jerarquía.

**.tracking_number

Si cada uno de tus proveedores aguas abajo anida los números de seguimiento de forma distinta, esta única expresión los encontrará en todas las versiones del payload. Esa es la definición de resiliencia estructural. Convierte la búsqueda frágil de una clave concreta en una búsqueda flexible de la verdad.

Patrón avanzado: reestructuración de datos sobre la marcha

JSONata permite reconstruir el objeto JSON completo en una sola pasada.

orders.{ "order_id": ID, "summary": $join(items.name, ', ') }

En código tradicional, esto requiere mapeo de objetos, concatenación de cadenas e iteración de arrays. En JSONata es una proyección declarativa del estado deseado. Resulta especialmente potente cuando necesitas enviar un resumen simplificado de un evento complejo a una notificación de Slack o a una app móvil.

Datos sin tablas en producción: seguridad y validación

Los críticos suelen preguntar: «Si no usamos esquemas, ¿cómo evitamos que entre basura en nuestro sistema?».

La respuesta es que sin esquema != sin validar. Simplemente trasladamos la validación al nivel del vertex.

Caso práctico: la malla de ingesta de datos en 50 regiones

Imagina una flota IoT global que ingiere telemetría de muchas regiones, cada una con una versión ligeramente distinta del firmware de sus sensores. Cada región tiene su propio «dialecto» de JSON.

El reto

Supongamos que el equipo parte de un sistema de ingesta tradicional basado en SQL con un esquema de tabla estricto. Cada vez que se despliega una actualización de firmware en una sola región, el pipeline de ingesta de esa región se rompe, porque el nuevo firmware añade un campo battery_health_v2 para el que la base de datos no tiene columna. El equipo de datos acaba en un modo permanente de «apagar incendios», ejecutando comandos ALTER TABLE en muchas bases de datos de producción y perdiendo eventos en cada ventana de mantenimiento.

La solución con SchemaBridge

Ahora imagina que el mismo equipo adopta una estrategia sin esquema.

1. Captura universal: todas las regiones apuntan sus datos al mismo entry point de SchemaBridge. A la capa de ingesta no le importa el esquema; persiste cada evento en bruto con su ejecución.

2. Mapeo en lectura: el equipo crea un paso de normalización por versión de firmware. Las aristas condicionales enrutan cada evento en bruto al paso adecuado según su campo de versión de firmware.

3. Actualizaciones sin código: cuando se lanza una nueva versión de firmware, no hay base de datos que actualizar. El equipo duplica el paso existente, actualiza el mapeo JSONata para incluir los nuevos campos y despliega.

El resultado probable

Conclusión: la velocidad es una decisión de diseño

Los esquemas estrictos son una elección. Una elección que prioriza la seguridad estática sobre la velocidad dinámica. En un sistema cerrado, es una elección válida. En un ecosistema conectado y distribuido, es una elección que conduce al fracaso.

Diseña tus sistemas para el mundo tal como es: impredecible, cambiante y jerárquico. Diseña para la velocidad. Diseña con SchemaBridge. Al abrazar la fluidez de los datos, desbloqueas la capacidad de construir, escalar e innovar a una velocidad con la que tus competidores —atrapados en sus DTO rígidos y sus migraciones de base de datos— solo pueden soñar.

Véase también: Dominar los fan-outs: el paso de la ingesta a la ejecución con el vertex Spawner, que reparte trabajo de alto volumen entre muchos elementos con backpressure acotado.

Explorar