La interrupción que no viste venir
Un equipo de productores renombra un campo. Lo prueban contra su propio servicio, actualizan su documentación interna y despliegan. El equipo de consumidores se entera cuando su cola de mensajes fallidos empieza a llenarse a las 3 a.m. Esto no es un escenario hipotético. Es la clase de fallo silencioso más común en las arquitecturas orientadas a eventos, y ocurre precisamente porque la gobernanza de esquemas se trató como algo deseable en lugar de un contrato estricto.
La versión más sutil es peor. Debido a cómo algunos deserializadores de JSON y Avro manejan los campos ausentes, un consumidor puede no lanzar ninguna excepción. Asigna null a la variable y sigue ejecutándose. Un caso bien documentado involucró a un modelo de fraude tomando decisiones sobre datos faltantes durante casi un mes antes de que alguien lo notara. Sin alertas, sin errores, solo resultados silenciosamente incorrectos.
Los registros de esquemas existen para prevenir exactamente esto. Pero un registro por sí solo no es suficiente, y entender por qué requiere ser específico sobre lo que estos sistemas realmente hacen y dónde se detienen.
Qué hace realmente un registro de esquemas
Un registro de esquemas es un almacén centralizado que asigna un ID entero único a cada versión de esquema registrada. El formato de cable de Confluent lo codifica de forma compacta: cada payload de mensaje lleva un prefijo de cinco bytes, un byte mágico con valor 0x00 seguido de un ID de esquema de cuatro bytes en formato big-endian. El payload no incluye la definición del esquema, por lo que cada consumidor realiza una búsqueda en el registro por ID, almacenada en caché de forma indefinida ya que los IDs son inmutables.
Este diseño significa que productores y consumidores nunca necesitan embeber ni negociar esquemas en tiempo de ejecución. También significa que si el registro no está disponible y la caché está fría, la deserialización falla. El registro es infraestructura, no un añadido secundario.
Tres registros dominan el ecosistema de código abierto. Confluent Schema Registry es la implementación de referencia original, disponible bajo una licencia que restringe la redistribución comercial. Apicurio Registry (Apache 2.0, respaldado por Red Hat) admite Avro, JSON Schema y Protobuf, además de formatos adicionales como OpenAPI, AsyncAPI y GraphQL; puede almacenar esquemas en PostgreSQL o en un topic de Kafka mediante su opción de almacenamiento KafkaSQL. Karapace (Apache 2.0, Aiven) ofrece una API compatible con Confluent con almacenamiento respaldado en Kafka y un proxy REST; su documentación describe autenticación OIDC con autorización basada en roles opcional. Los tres admiten los formatos de serialización más relevantes en pipelines de Kafka: Avro, JSON Schema y Protobuf.
Modos de compatibilidad: la parte que la mayoría de los equipos configura mal
Aquí es donde reside la complejidad real y donde se originan la mayoría de los incidentes en producción. Confluent Schema Registry define cuatro modos de compatibilidad, cada uno con una variante transitiva.
- BACKWARD: los consumidores que usan el nuevo esquema pueden leer datos escritos con el esquema anterior. Se pueden añadir campos opcionales o eliminar campos. Es el modo predeterminado, y la razón por la que lo es en Kafka es específicamente para que los consumidores puedan rebobinar al inicio de un topic y reprocesar datos históricos.
- FORWARD: los consumidores que usan el esquema anterior pueden leer datos escritos con el nuevo esquema. Se pueden eliminar campos opcionales o añadir campos. Es útil cuando necesitas desplegar productores antes que consumidores.
- FULL: backward y forward simultáneamente. Solo se permite añadir o eliminar campos opcionales. Es la opción más conservadora para topics de larga duración.
- Variantes TRANSITIVE: BACKWARD_TRANSITIVE, FORWARD_TRANSITIVE y FULL_TRANSITIVE verifican la compatibilidad contra todas las versiones anteriores del esquema, no solo la más reciente. Los modos no transitivos solo comprueban contra la versión inmediatamente anterior, lo que significa que una cadena de migraciones individualmente válidas puede acumular un delta total incompatible.
Para Kafka Streams específicamente, solo se admite la compatibilidad BACKWARD. Si ejecutas topologías de Streams, esa decisión ya está tomada por ti.
Un registro de esquemas sin un modo de compatibilidad correctamente configurado no previene esquemas incorrectos. Solo los registra. Es un libro de contabilidad, no un filtro de acceso. La aplicación de compatibilidad solo se activa cuando se establece explícitamente un modo distinto de NONE, ya sea por subject o de forma global.
El modo BACKWARD predeterminado no es BACKWARD_TRANSITIVE. Un equipo que migra a través de tres versiones de esquema, cada una individualmente compatible con la anterior, puede terminar con una versión tres que no puede leer datos de la versión uno. Si los consumidores pueden rebobinar al inicio del topic, esa brecha importa. BACKWARD_TRANSITIVE la cierra.
Los modos de fallo que no te alertan de inmediato
El fallo dramático, una excepción de deserialización que mata a un consumidor, es en realidad el caso fácil. Lo ves, haces rollback y lo corriges. Los fallos peligrosos son los que siguen ejecutándose.
Considera un cambio de estrechamiento de tipo: un productor cambia un campo de long a int. La mayoría de los mensajes encajan. Una pequeña fracción de valores supera el rango del entero. En un stream de alto rendimiento, incluso una tasa de fallo del 0,1% significa un goteo continuo de eventos fallidos hacia las colas de mensajes fallidos, difícil de distinguir del ruido normal, mientras que el 99,9% de los eventos se procesan correctamente. El stream parece sano. Las alertas no se disparan. Los datos son incorrectos.
La deriva de esquemas, donde distintos servicios acumulan versiones de esquema conflictivas con el tiempo, agrava esto. Las consultas analíticas empiezan a devolver resultados incorrectos. Los campos de PII que las herramientas de cumplimiento rastreaban desaparecen o se mueven. El reprocesamiento de datos históricos se vuelve costoso o imposible porque el esquema en el momento de escritura ya no es recuperable.
Gobernanza de esquemas en la práctica: lo que necesita el pipeline
Gestionar bien la gobernanza de esquemas requiere tres elementos funcionando en conjunto: un registro con la aplicación de compatibilidad configurada, una puerta de CI/CD que valide los cambios de esquema antes de que lleguen a producción, y observabilidad que muestre los fallos relacionados con esquemas de forma diferenciada.
La puerta de CI/CD no es negociable. Un cambio de esquema propuesto debe validarse contra el registro en el pipeline de preproducción, antes de que se despliegue el productor. Si el cambio viola el modo de compatibilidad configurado, el pipeline falla. Esto detecta los cambios disruptivos en el momento en que son más baratos de corregir, antes de que cualquier consumidor se vea afectado.
La observabilidad debe cubrir registros rechazados, errores de serialización, errores de deserialización, volumen de la cola de mensajes fallidos y lag de consumidores en una única vista de incidente. Los errores de serialización en el lado del productor y los errores de deserialización en el lado del consumidor son señales distintas; confundirlos ralentiza el diagnóstico.
En DIVERSITY ejecutamos NATS JetStream como backbone propio de streaming de eventos en producción. NATS JetStream no incluye de serie un registro de esquemas compatible con Confluent que aplique los modos de compatibilidad BACKWARD/FORWARD/FULL; el registro de esquemas interno jsm.go cubre los tipos de mensajes de la API del propio servidor. Para la aplicación completa de contratos de esquema entre productor y consumidor en nuestros pipelines gestionados compatibles con Kafka, operamos infraestructura de registro dedicada, y tratamos la configuración del modo de compatibilidad y la puerta de CI/CD como parte del contrato de servicio, no como añadidos opcionales. Esa postura operativa, respaldada por la certificación ISO 27001 y un SLA contractual de disponibilidad del 99,9%, es lo que convierte la gobernanza de esquemas en una garantía de fiabilidad y no en una recomendación de mejor esfuerzo.
Cómo elegir el modo de compatibilidad adecuado para tu topic
No existe una respuesta universal, pero sí heurísticas claras. Usa BACKWARD cuando los consumidores vayan a reprocesar datos históricos y controles el despliegue del productor. Usa FORWARD cuando los productores se desplieguen antes que los consumidores y los consumidores antiguos deban seguir funcionando durante la transición. Usa FULL cuando el topic sea de larga duración, lo consuman muchos equipos independientes y los cambios de esquema deban ser seguros en ambas direcciones. Añade la variante TRANSITIVE siempre que tu historial de despliegues abarque más de dos versiones de esquema y no puedas garantizar que los consumidores estén siempre en la última versión.
Configura los modos de compatibilidad por subject, no solo de forma global. Un topic interno de alta rotación y un bus de eventos público utilizado por socios downstream tienen perfiles de riesgo distintos y deben tener niveles de aplicación diferentes. El registro te permite configurarlo así; úsalo.
El contrato que mantiene los servicios independientes
Las arquitecturas orientadas a eventos prometen un acoplamiento débil: productores y consumidores se despliegan de forma independiente, escalan de forma independiente y evolucionan de forma independiente. Esa promesa solo se cumple si el contrato de mensajes entre ellos se aplica en algún lugar. Sin un registro de esquemas con aplicación activa de compatibilidad y una puerta de CI/CD delante de él, ese contrato existe solo en la documentación, lo que equivale a decir que no existe en absoluto.
Un registro de esquemas tratado como opcional acabará demostrando que no lo es. La única pregunta es si lo descubres en una revisión de código o a las 3 a.m. con un modelo de fraude que lleva un mes ejecutándose sobre datos nulos.




