Con una cuenta desbloqueas el cuestionario, el foro de dudas y el tutor con IA de esta lección, además del registro de progreso y el certificado verificable al terminar «Sistemas Distribuidos para Misiones Espaciales».
En un clúster donde cada app es un equipo (o un despliegue) independiente, el contrato — la forma exacta de los datos que viajan entre dos apps — es la única frontera que de verdad importa. No importa qué lenguaje use el productor de un evento ni qué base de datos use el consumidor: lo único que ambos deben acordar es la forma del JSON que se intercambian. Este curso adopta JSON Schema (draft 2020-12) como el lenguaje formal para describir esa forma, porque es verificable por máquina en ambos extremos — no es documentación que alguien pueda ignorar, es una regla que el código aplica.
Los cuatro pilares de un schema
Un contrato JSON Schema útil en este contexto se apoya en cuatro palabras clave:
type: el tipo de dato esperado ("object", "string", "integer", "number", "boolean", "array").
properties: qué campos existen dentro de un objeto y el schema de cada uno.
required: qué campos son obligatorios — su ausencia hace inválido el payload completo.
enum: una lista cerrada de valores permitidos para un campo (por ejemplo, el nombre de una estación terrena entre las que existen).
Un quinto keyword, additionalProperties: false, cierra el contrato: prohíbe cualquier campo que no esté explícitamente declarado en properties. Sin él, un productor podría añadir silenciosamente un campo nuevo y ningún consumidor lo notaría hasta que dependiera de él — con additionalProperties: false, ese campo extra hace que el payload sea rechazado de inmediato, en vez de colarse sin control.
Ejemplo completo: el contrato pass.completed.v1
Consideremos el evento que la estación terrena publica cuando termina de rastrear un pase de satélite:
Un payload válido: {"norad_id": 25544, "estacion": "orbiteye-mx", "inicio_utc": "2026-07-29T14:00:00Z", "fin_utc": "2026-07-29T14:11:00Z", "resultado": "completada"}. Un payload inválido por dos razones a la vez: {"norad_id": 25544, "estacion": "orbiteye-ar", "inicio_utc": "2026-07-29T14:00:00Z", "resultado": "completada"} — falta el campo requerido fin_utc, y "orbiteye-ar" no está en el enum de estaciones.
Versionado: cuándo nace un .v2
El sufijo .v1 en el nombre del contrato no es decorativo: es la señal de que los contratos evolucionan y de que esa evolución debe ser explícita. La regla práctica es: añadir un campo opcional nuevo es un cambio compatible (los consumidores existentes que no lo conocen simplemente lo ignoran); eliminar un campo, hacer obligatorio un campo que antes era opcional, o cambiar el tipo o el significado de un campo existente es un cambio incompatible, y exige publicar pass.completed.v2 mientras .v1 sigue viviendo el tiempo que los consumidores necesiten para migrar. Nunca se modifica el contrato .v1 de forma que rompa a un consumidor que no se enteró del cambio.
Validación doble: no confíes ni en tu hermano
La disciplina que hace que esto funcione en la práctica es la validación doble: el productor valida su propio payload contra el schema antes de publicarlo (para no propagar su propio bug al resto del clúster), y el consumidor valida de nuevo al recibirlo (porque no puede asumir que el productor validó correctamente, o que no hay un bug de red, o que no está hablando con una versión vieja del productor). Es redundante a propósito: la redundancia es la que convierte un contrato de "documentación que alguien puede ignorar" en una garantía que el propio código hace cumplir en ambos extremos.
Los contratos viven en el repositorio, como documentación ejecutable
Los contratos de este clúster no son un documento Word aparte que se desactualiza en silencio: viven como archivos JSON Schema dentro del repositorio de cada app, junto al código que los usa, y con tests que verifican que el schema y el modelo de datos interno aceptan y rechazan exactamente los mismos payloads. Si el modelo cambia y el schema no se actualiza a la vez, el test lo detecta antes de que llegue a producción. Y una idea final que conviene interiorizar pronto: el seed no es la verdad — los datos con los que arranca una base de datos de desarrollo son solo un punto de partida cómodo, nunca la fuente de verdad sobre qué contratos existen o qué forma tienen; esa fuente es siempre el schema versionado en el repositorio.
Implementa tú mismo un validador mínimo y aplícalo al contrato del ejemplo:
Playground · javascript
¿Qué campo del schema evita que un productor "cuele" silenciosamente un campo nuevo que ningún consumidor espera?
8. Custodia de datos: un backup no probado no es backup