La evolución de esquema falla cuando el solapamiento de versiones no se mide
Un cambio de esquema falla en producción no porque la migración esté mal sino porque el solapamiento de versiones no se mide. Theorem 3 sobre compatibilidad hacia atrás y adelante, expand-and-contract, y el contrato wire en la frontera.

La evolución de esquema falla cuando el solapamiento de versiones no se mide
Un cambio de esquema suele ser uno de los tipos de cambio más difíciles para un sistema de software, y el artículo de ByteByteGo «Schema Evolution: Changing the Contract Without Breaking What Runs» abre con la razón honesta del porqué: la migración corre limpia en staging, y servicios no relacionados empiezan a fallar en producción, y nada estaba mal con la migración en sí misma (ByteByteGo, «Schema Evolution: Changing the Contract Without Breaking What Runs», 20 ago. 2026, https://blog.bytebytego.com/p/schema-evolution-changing-the-contract). El fallo no es el cambio. El fallo es el supuesto de que solo una versión de esquema está en juego. Filas escritas hace años son leídas por código que desde entonces ha sido reemplazado. Mensajes sentados en una cola se publicaron antes de que el consumidor actual se escribiera. Versiones de app mobile de hace dieciocho meses siguen instaladas y siguen llamando a la API. La propiedad «sin rotura en un cambio de esquema» se garantiza exactamente cuando el mecanismo — compatibilidad hacia atrás y hacia adelante más la secuenciación expand-and-contract — está implementado y midiendo si dos versiones siguen vivas. Theorem 3: una propiedad se garantiza exactamente cuando su mecanismo está implementado y midiendo.
Conclusiones clave
- Los cambios de esquema rompen producción no porque la migración esté mal, sino porque entra en vigor mientras dos versiones de la aplicación siguen ejecutándose contra la misma base de datos, y solo una de esas versiones referenciaba el esquema modificado (ByteByteGo, 20 ago. 2026).
- Más de una versión de esquema está siempre en juego: filas escritas hace años, mensajes en cola antes del consumidor actual, apps mobile de dieciocho meses que todavía llaman a la API — datos escritos bajo una versión de esquema se leen bajo otra.
- «Sin rotura» es una propiedad que se mantiene exactamente cuando la compatibilidad hacia atrás y hacia adelante se implementa como mecanismos y el solapamiento de versiones se mide. Un cambio de esquema sin mecanismo de compatibilidad es un cambio de contrato sin garantía.
- Theorem 3: una propiedad se garantiza exactamente cuando su mecanismo está implementado y midiendo. Expand-and-contract es el mecanismo; la línea de deprecation que rastrea el último lector viejo es la medida.
Más de una versión de esquema está siempre en juego
La introducción de ByteByteGo nombra el hecho estructural que cada postmortem de cambio de esquema redescubre: la migración corre sin problemas en staging, y servicios no relacionados fallan en producción, y la investigación no encuentra nada mal con la migración — entró en vigor mientras dos versiones de la aplicación todavía se ejecutaban contra la misma base de datos, y solo una de esas versiones referenciaba el esquema modificado. Eso no es una brecha staging-producción. Es un supuesto de una versión que se encuentra con una realidad de varias versiones. El staging prueba la migración contra el código nuevo. La producción ejecuta la migración contra el código nuevo y el código viejo y los datos viejos que el código viejo escribió y los mensajes en cola que el viejo publicador escribió. El entorno de staging es una topología de versión única; la producción es una topología de solapamiento de versiones.
[UNIQUE INSIGHT] El solapamiento de versiones no está acotado por la ventana de deploy. La introducción de ByteByteGo es explícita: filas escritas hace años pueden ser producidas por código de aplicación que desde entonces ha sido reemplazado. Mensajes sentados en una cola se publicaron antes de que se escribiera la versión actual del consumidor. Versiones de app mobile de hace dieciocho meses siguen instaladas en dispositivos reales y siguen llamando a la API. La ventana de deploy es el solapamiento más pequeño; el solapamiento de estado duradero — filas viejas, mensajes en cola, clientes mobile instalados — es el solapamiento que realmente te rompe. Un plan de cambio de esquema que solo contempla la ventana de deploy está midiendo el solapamiento de versiones más pequeño y afirmando la propiedad sobre el mayor. Esa es la brecha entre el mecanismo que está implementado (coordinación de ventana de deploy) y el mecanismo que garantizaría la propiedad (seguimiento completo del solapamiento de versiones, incluyendo estado duradero y clientes instalados).
El Honest Architect lee la afirmación de ByteByteGo como una afirmación topológica, no una afirmación de proceso. «More than one schema version is always in play at the same time» es un enunciado sobre la forma de un sistema distribuido: escritores y lectores están desacoplados en el tiempo, y el esquema es el contrato que cubre la brecha temporal. Un cambio al contrato es seguro solo si cubre cada lector que sigue vivo, incluyendo lectores que estaban vivos cuando se escribieron los datos y lectores que estarán vivos cuando los datos se lean. La compatibilidad hacia atrás y hacia adelante son dos mecanismos diferentes, no uno.
La compatibilidad hacia atrás y hacia adelante son dos mecanismos diferentes
La compatibilidad hacia atrás (backward) es la propiedad de que el código nuevo lee datos viejos. La compatibilidad hacia adelante (forward) es la propiedad de que el código viejo lee datos nuevos. Parecen simétricas en el nombre y no son simétricas en el mecanismo. La compatibilidad hacia atrás es una propiedad que el autor del código nuevo puede garantizar tolerando los campos que faltan — el código nuevo sabe cómo era el esquema viejo. La compatibilidad hacia adelante es una propiedad que el autor del código nuevo no puede garantizar por sí solo, porque el código viejo ya está desplegado; la única garantía es hacer el cambio de una forma que el código viejo ya tolera (añadir campos opcionales, no eliminar campos que el código viejo lee, no cambiar la semántica de los campos). La compatibilidad hacia atrás es una garantía en tiempo de escritura; la compatibilidad hacia adelante es una restricción en tiempo de diseño sobre el propio cambio.
El artículo de ByteByteGo promete cubrir «which changes break consumers, which do not, and the qualifiers that decide it» — y los calificadores son el mecanismo. Añadir un campo opcional es compatible hacia atrás (el código nuevo lee datos viejos que carecen del campo) y compatible hacia adelante (el código viejo lee datos nuevos que tienen un campo extra que ignora). Renombrar un campo no es ninguna de las dos: el código viejo lee datos nuevos y busca el nombre viejo del campo, no lo encuentra, se rompe. Eliminar un campo que el código viejo lee es incompatible hacia adelante. Cambiar el tipo o la semántica de un campo es ambos incompatible hacia atrás y hacia adelante incluso si los bytes del cable son idénticos, porque el contrato es el significado, no los bytes. El Honest Architect trata un renombrado o un cambio de tipo como una rotura de contrato, no un cambio de esquema — viola un supuesto que un lector vivo está haciendo.
[PERSONAL EXPERIENCE] Los tipos de cable de Everythink se definen una vez, en Zod, en @everythink/types, y las respuestas se analizan en la frontera de red. Eso es un registro de esquema en la frontera, no solo una definición de tipo. El esquema Zod es el contrato; el parse-at-boundary es la medida — un payload que no coincide con el esquema sale como un ApiError tipado, nunca un crash. Etiquetamos eso Production ✅ porque el mecanismo (parse-at-boundary) está implementado y la medida (el error tipado) corre en cada respuesta. Un cambio de esquema en el backend sin un cambio de esquema Zod correspondiente es un cambio de contrato sin una medida del lado del consumidor — Partial ⚠️ hasta que el esquema Zod se actualice y el parse-at-boundary capture el desvío.
La invariante del Oracle — las probabilidades se normalizan en exactamente un lugar, everythink-oracle::ensemble, de modo que los consumidores pueden confiar en sum(probability) ≈ 1.0 — es un contrato de esquema que el código aguas abajo lee. Un cambio de la ubicación de normalización o del orden de ordenación sería una rotura de contrato aunque los bytes del cable parecieran idénticos, porque el contrato es la garantía en la que los consumidores confían. Etiquetamos esa invariante Production ✅ porque el mecanismo (único sitio de normalización) está implementado y la medida (los tests de ensemble) corre. La disciplina de evolución de esquema para esa invariante es: nunca mover el sitio de normalización sin una secuencia expand-and-contract que permita a los consumidores viejos seguir leyendo la garantía vieja mientras los nuevos leen la nueva.
Expand and Contract — el move topológico
Expand and Contract es el mecanismo que hace seguro un cambio de contrato bajo solapamiento de versiones. Expand: añadir el nuevo elemento de esquema de una forma que sea tanto compatible hacia atrás como hacia adelante. Dejar que los lectores viejos sigan leyendo el contrato viejo y que los lectores nuevos empiecen a leer el nuevo. Esperar a que el solapamiento de versiones se vacíe — clientes viejos se actualicen, mensajes viejos se consuman, filas viejas envejezcan y salgan. Contract: eliminar el elemento de esquema viejo una vez que ningún lector vivo lo referencia. La fase expand es la expansión topológica (dos rutas coexisten); la fase contract es la contracción topológica (una ruta permanece).
La medida que regula la fase contract es la línea de deprecation que rastrea el último lector viejo. ByteByteGo promete «versioning strategies and deprecation timelines» — y la línea de deprecation es la medida que convierte expand-and-contract en una propiedad garantizada en lugar de una esperanza. El Honest Architect etiqueta un plan expand-and-contract sin una medida del último lector viejo como Partial ⚠️: el mecanismo (expand, esperar, contract) está implementado, pero la medida que regula el contract no lo está. Un plan que rastrea el último lector viejo — por telemetría de versión de cliente, por edad de mensaje en cola, por etiquetas de versión de esquema de fila — y solo contrái cuando ese contador llega a cero es Production ✅.
[ORIGINAL DATA] La disciplina de migración de Everythink etiqueta esto directamente. Cada migración .up.sql tiene una .down.sql correspondiente — ese es el camino de rollback, el contrato de que un expand fallido puede deshacerse. La .down.sql es la red de seguridad de la fase expand: si el expand rompe un lector vivo, contraes el cambio de esquema (ejecutas la migración down) y los lectores viejos reanudan. Etiquetamos el camino de rollback Production ✅ porque cada migración tiene uno y el migrador impone el emparejamiento. Una migración que añade y elimina en un solo paso es un cutover, no un expand-and-contract — Partial ⚠️ si el código viejo sigue vivo, porque la fase contract corre dentro del solapamiento de versiones.
La caché geo del World Monitor lleva la misma disciplina en una forma diferente. Los ids de GeoSignal son uuidv5 deterministas (source, native_id) — la reingesta actualiza, nunca crea duplicados. Eso es un mecanismo de compatibilidad hacia adelante para la caché: una nueva ingesta de la misma señal actualiza la fila en lugar de crear una segunda, de modo que un lector que vio el id viejo y un lector que ve el id nuevo leen la misma fila. La estabilidad del id es el contrato; el uuidv5 determinista es el mecanismo; el upsert es la medida (el conteo de filas no crece con la reingesta). Etiquetamos eso Production ✅ porque el mecanismo está implementado y la estabilidad del conteo de filas es observable. Un cambio de esquema al esquema de ids sería un renombrado de la clave primaria — el cambio más incompatible hacia adelante que existe — y requeriría un expand-and-contract que escriba ambos ids y migre los lectores antes de eliminar el viejo.
Lo que un Honest Architect lee en una introducción paywalled
El artículo de ByteByteGo está paywalled tras el encabezado de sección «Version Overlap», y el Honest Architect no fabrica el cuerpo. Lo visible es la afirmación estructural — más de una versión de esquema está siempre en juego, la migración es limpia en staging y rompe en producción, el fallo no es la migración sino el solapamiento de versiones — y esa afirmación basta para aplicar la disciplina de etiquetado. La introducción visible da: la realidad multiversión (Production ✅ como hecho estructural de los sistemas distribuidos), la brecha staging-producción como diferencia de topología versión-única-vs-multiversión (Production ✅ como encuadre), y la promesa de compatibilidad hacia atrás/adelante, expand/contract, registros de esquema y líneas de deprecation como mecanismos.
La regla del Honest Architect: citar la fuente real, nunca fabricar una URL o métrica, nunca afirmar que el artículo dijo algo que no dijo. La introducción dice que la migración corre limpia en staging y rompe en producción porque dos versiones se ejecutan contra la misma base de datos. Esa es la afirmación citada. El resto del análisis es el mecanismo aplicado al propio stack de Everythink, etiquetado contra nuestra propia implementación, no atribuido a ByteByteGo. La afirmación cross-domain (expand-and-contract es el mismo move topológico en un esquema de base de datos y en un ensemble de previsión) es Partial ⚠️ porque la forma se comparte y los dominios están separados.
El límite de alcance: Everythink es una plataforma de previsión civil y defensiva, no una consultoría de bases de datos. La lección de evolución de esquema es cross-domain — un cambio de contrato es seguro solo cuando el solapamiento de versiones se mide — y se aplica tanto si el contrato es un esquema de base de datos, un payload de API, un tipo Zod o una invariante de ensemble de previsión. No se promete ningún resultado de token, wallet o community-credit; esos son Roadmap 🔵, sujetos a revisión Howey. Un ítem de Roadmap nunca se promociona silenciosamente a Production basándose en una forma de evolución de esquema.
Preguntas frecuentes
¿Por qué un cambio de esquema rompe producción cuando la migración corrió limpia en staging?
Porque el staging prueba la migración contra el código nuevo solamente, y la producción ejecuta el código nuevo junto con código viejo, datos viejos, mensajes en cola y clientes mobile instalados que se escribieron bajo el esquema viejo. La migración es limpia; el solapamiento de versiones no lo es. El fallo no es el cambio — es el supuesto de que solo una versión de esquema está en juego. Theorem 3: la propiedad «sin rotura» se garantiza solo cuando el mecanismo de solapamiento de versiones está implementado y midiendo.
¿Cuál es la diferencia entre compatibilidad hacia atrás y hacia adelante?
La compatibilidad hacia atrás (backward) es la propiedad de que el código nuevo lee datos viejos — el autor del código nuevo la garantiza tolerando los campos que faltan. La compatibilidad hacia adelante (forward) es la propiedad de que el código viejo lee datos nuevos — el autor del código nuevo no puede cambiar el código viejo, así que la única garantía es hacer el cambio de una forma que el código viejo ya tolera (añadir campos opcionales, no eliminar ni renombrar campos que el código viejo lee). La compatibilidad hacia atrás es una garantía en tiempo de escritura; la compatibilidad hacia adelante es una restricción en tiempo de diseño sobre el propio cambio.
¿Qué es expand and contract?
Expand: añadir el nuevo elemento de esquema de una forma que sea tanto compatible hacia atrás como hacia adelante. Dejar que lectores viejos y nuevos coexistan. Esperar a que el solapamiento de versiones se vacíe — clientes viejos se actualicen, mensajes viejos se consuman, filas viejas envejezcan y salgan. Contract: eliminar el elemento de esquema viejo una vez que ningún lector vivo lo referencia. La fase expand es una expansión topológica (dos versiones de contrato coexisten); la fase contract es una contracción topológica (una versión permanece).
¿Cómo impone Everythink la evolución de esquema en la frontera del cable?
Los tipos de cable se definen una vez, en Zod, en @everythink/types. Las respuestas se analizan en la frontera de red; un payload que no coincide con el esquema sale como un ApiError tipado, nunca un crash. El esquema Zod es el contrato; el parse-at-boundary es la medida. Un cambio de esquema de backend sin un cambio de esquema Zod correspondiente es un cambio de contrato sin una medida del lado del consumidor — Partial ⚠️ hasta que el esquema Zod se actualice.
¿Promete Everythink que los cambios de esquema nunca rompen a los consumidores?
No. Prometemos el mecanismo: parse-at-boundary Zod, emparejamiento .up.sql/.down.sql, invariante Oracle de sitio-único-de-normalización, uuidv5 determinista para la caché del World Monitor. La propiedad «sin rotura en un cambio dado» se mantiene cuando el cambio sigue expand-and-contract y la línea de deprecation rastrea el último lector viejo. Un cambio que hace cutover dentro del solapamiento de versiones es Partial ⚠️. No se promete ningún resultado de token, wallet o community-credit; esos son Roadmap 🔵.
Sources
- ByteByteGo, «Schema Evolution: Changing the Contract Without Breaking What Runs», 20 ago. 2026, recuperado 2026-08-23, https://blog.bytebytego.com/p/schema-evolution-changing-the-contract
Si tu equipo está listo para medir el solapamiento de versiones, no solo la ventana de deploy, crea tu red — la topología enruta dos versiones de contrato, la frontera parsea, el camino de rollback deshace.

La personalización es la separación de mecanismos, no los pesos abiertos
Inkling está diseñado para ser personalizado no por su licencia Apache 2.0 sino porque cada decisión arquitectónica aísla una propiedad medible detrás de su propio mecanismo. El balanceo basado en sesgo es la instancia más pura de Theorem 3: una propiedad garantizada por un mecanismo que no compite con el objetivo principal.
→ →
Geolocalizar una dirección MAC necesita el mecanismo, no el identificador
Una dirección MAC no contiene GPS, pero una base de datos de wardriving más una fusión de centroide ponderado por señal puede geolocalizar un punto de acceso fijo. Theorem 3: la propiedad viene del mecanismo, no del identificador.
→ →
El enriquecimiento de datos es coherencia, no volumen
Más datos no significan automáticamente mejor insight. Teorema 3: la propiedad (mejor insight) viene del mecanismo (verificación de coherencia entre puntos de datos), no del volumen. El valor son mejores preguntas, no certeza.
→ →Construye tu mundo sobre un motor que demuestra lo que afirma.
Crea tu propia red en el motor que funciona desde 2016 — o habla con el equipo detrás de los 21 artículos.
