← Volver al método
Para quien construye

Contratos de datos y dominios independientes

Tres repositorios que no se pisan, un contrato escrito por cada flujo y una única puerta entre ellos. Es lo que se toma de la idea de data mesh, adaptado a un laboratorio pequeño.

3dominios con repositorio propio
46flujos, cada uno con su contrato
7tablas Gold: la puerta entre dominios
0reglas de gobierno rotas hoy, comprobadas sobre todos los contratos

Cifras a 6 de octubre de 2026.

1 · Qué se toma de un data mesh (y qué no)

Un data mesh plantea que los datos no los gestiona un equipo central sino los dominios que los conocen, que cada dominio publica sus datos como un producto con una interfaz estable, y que el gobierno es federado: unas reglas comunes, aplicadas por cada dominio. Está pensado para organizaciones con muchos equipos. Aquí no hace falta tanto, pero el problema de fondo es el mismo: cambiar una parte sin romper las demás.

Lo que se toma

Cada repositorio es dueño de lo suyo y no escribe en el de otro. Cada flujo declara qué lee y qué produce. Lo que cruza de un dominio a otro es un producto con nombre, no un fichero que alguien sabe dónde está. Las reglas comunes viven en un documento aparte.

Lo que no es

No hay catálogo corporativo ni plataforma de autoservicio. Los dominios comparten una carpeta de datos: la frontera entre ellos es de convención, no de seguridad.

2 · Los dominios

Dominiofeb-scoutingIngesta de la FEB, Silver y Gold. Es el productor.
PuertaGoldSiete tablas: lo único que sale del dominio
Dominiopost-game-agentEstadística, tarjetas, vídeos y exportación: seis flujos de Prefect
Dominiomolokai-webLee ficheros estáticos; declara su contrato aunque no use Prefect

Cada uno tiene su repositorio, sus pruebas y su ciclo de cambios. Los tres siguen la misma convención: sus flujos viven en carpetas por capa y cada uno lleva su contrato. El agente de contenido tardó en entrar en ella (era un conjunto de herramientas de terminal) y lo hizo en octubre: la rutina de después de una jornada, que antes eran varios comandos a mano, es ahora un flujo que llama a los demás en orden, con los mismos comandos por debajo. La web, que no es un flujo de Prefect, declara igualmente qué lee, para que el mapa llegue hasta ella. Un cuarto repositorio, data-governance, no contiene código: contiene la ley. Define las capas, cómo se nombra una entidad, qué clasificación de sensibilidad lleva y quién puede leer qué. Se separa a propósito: quien escribe las reglas no debería ser quien las cumple.

3 · El contrato de un flujo

Cada flujo lleva, junto a su código, un fichero de configuración con un bloque data_contract: qué entidades lee, cuáles produce, dónde viven, en qué formato y con qué clasificación, y qué otros flujos lo llaman. Así luce el de uno de los Gold:

# flows/gold/player_games/settings.yaml (recortado)
data_contract:
  inputs:
    - entity: "silver_player_boxscore"
      path:   "feb-scouting/silver/official-boxscore/player_boxscore"
      format: "delta"
    - entity: "silver_derived_minutes"
      path:   "feb-scouting/silver/derived-minutes/derived_minutes"
      format: "delta"
    - entity: "gold_matches"
      path:   "feb-scouting/gold/matches/matches"
      format: "delta"
  outputs:
    - entity: "gold_player_games"
      path:   "feb-scouting/gold/player-games/player_games"
      format: "delta"
      partition_by: ["season", "comp_id"]
      tier: gold
      classification: public

flow_dependencies:
  called_by: ["flows/gold/sync/flow.py:main"]

Un proyecto aparte, el observatorio, tiene una lista explícita de los dominios del laboratorio. Añadir uno es añadir una línea, siempre que siga la convención. De esa lista lee todos los contratos, aplica las reglas de gobierno a la vez y ve lo que ningún dominio puede ver solo: que lo que cruza una frontera sea Gold del productor.

Juntando todos esos contratos se puede dibujar el laboratorio entero, sin que nadie lo dibuje a mano: el mapa de los datos.

Tres convenciones lo hacen útil. El nombre de la entidad empieza por su capa (bronze_, silver_, gold_), así que nadie confunde un dato crudo con uno certificado. La ruta física sigue siempre el mismo patrón (dominio, capa, flujo, conjunto de datos), de modo que de la ruta se deduce quién lo produce. Y la clasificación se propaga de forma conservadora: un dato derivado hereda la más restrictiva de sus entradas.

4 · La regla que más cuesta: Gold no es un Silver con otro nombre

La regla central dice que lo que cruza la frontera de un dominio es siempre Gold del productor: nadie lee el Silver ni el Bronze de otro. Y su corolario, que es el que duele: Gold nunca es un ascenso de un Silver que ya existe, sino un artefacto nuevo, delgado, con solo lo que de verdad se consume fuera.

Deuda reconocidaUna deuda que ya no existe
Hasta hace unos días, el agente de contenido leía directamente las tablas Silver de feb-scouting. Funcionaba, pero rompía la propia regla del laboratorio: el agente es otro dominio y consumía Silver, no Gold. La excepción estaba escrita en el documento de gobierno, con un plan para retirarla, y está retirada desde el 6 de octubre.

Retirarla no fue cambiar una ruta. Al examinar qué hacía el consumidor con esos datos al leerlos, resultó que corregía cosas que son del productor, y que cualquier consumidor futuro habría tenido que redescubrir:

Subió al productorMinutos y +/- que el acta no trae

El acta oficial no da minutos en 2021-22 ni 2022-23, y solo en parte de 2023-24. El consumidor los reconstruía desde las sustituciones. Ahora los reconstruye feb-scouting y los marca como derivados.

Subió al productorUn id de jugador estable

El acta numera a los jugadores con ids que no son los del minuto a minuto ni los de otras temporadas. El consumidor lo arreglaba al exportar. Ahora el id estable viene de serie, y el del acta se conserva aparte.

Subió al productorPartidos sin acta

Siete partidos de liga de dos temporadas no los sirve la fuente. Su marcador se copiaba a mano en un fichero del consumidor. Ahora es una fuente manual del productor, con contrato.

Subió al productorClub con un solo nombre, y el tipo de competición

Un patrocinador cambia a mitad de curso y el club salía con dos nombres. Y la Copa Princesa vive dentro del identificador de la liga. Los dos se resuelven una vez, en Gold.

Tres Gold que casi no transforman nada
Los eventos, el estado del partido y los perfiles de tiro llegan a Gold con un único añadido: la fecha, la jornada y el tipo de competición del partido. Se mantienen igual porque lo que se obtiene con ellos no es la transformación sino el contrato: una puerta única, con nombre, que el consumidor puede leer sin enterarse de cómo está organizado el Silver por dentro. Si mañana el productor cambia esa organización, la puerta no se mueve.

Las posiciones de los jugadores siguen la misma lógica por el otro lado. Antes iban a ser un fichero que mantendría el consumidor. Ahora son una fuente manual de Bronze del productor: un CSV versionado, validado al entrar, que pasa por Silver y llega a Gold marcado con su origen (manual o de la plantilla). Lo que es del dato se arregla donde nace el dato.

5 · Cómo se comprueba que el cambio no rompió nada

Mover lógica entre repositorios es el tipo de cambio que sale bien en las pruebas y mal en lo publicado. Se hicieron tres comprobaciones que no dependían de la memoria de nadie:

  1. 1Misma derivación, mismo resultadoAntes de mover nada, la nueva reconstrucción de minutos se comparó con la del consumidor sobre 1.591 partidos: 0 diferencias, jugador a jugador y segundo a segundo.
  2. 2Los exports, antes y despuésSe generaron los ficheros que alimentan la web con el código viejo y con el nuevo, y se compararon uno a uno. Cierres, quintetos, asistencias, evolución, historial y los 322 partidos de 2021-22 salieron idénticos. Las diferencias aparecieron solo donde se esperaban mejoras, y se revisaron.
  3. 3La suite del consumidor como redSus 440 pruebas pasaron contra Gold. Y atraparon un fallo propio: una columna numérica se escribió como texto.
Error realUna errata que no rompía nada, hasta que se dibujó el mapa
Al aplicar la regla «todo dato que un flujo lee lo produce otro flujo», salió que el flujo de eventos decía leer perfiles de jugador en plural, mientras que quien los produce los llama en singular. En ejecución nunca falló, porque el flujo lee los ficheros directamente y no el nombre del contrato. Pero el linaje estaba roto en silencio: en el mapa, el dato aparecía sin origen. Es el tipo de error que un contrato solo sirve para encontrar si alguien lo lee.
Error realUna columna numérica que se volvió texto
En las temporadas más antiguas el acta no trae una de las valoraciones, así que, para esa partición, todos los valores estaban vacíos. La librería que escribe la tabla, al ver una columna entera vacía, la tipa como texto, y esa decisión contagió a toda la tabla: las sumas del consumidor fallaron al intentar sumar un número y una cadena. No se detectó mirando el dato, sino con la prueba de otro repositorio. Ahora cada columna numérica de Gold declara su tipo.
El cambio que sí se ve
Con el identificador estable, los perfiles de 2021-22 encuentran por fin la ficha de más jugadores (posición, altura, nacionalidad), y las ruedas de percentiles de 166 de ellos se comparan contra su posición en lugar de contra todos. Es una mejora, pero es un cambio de lo publicado, así que se revisa antes de reexportar.

6 · Lo que todavía no se hace

LímiteNo hay frontera real

Todo el almacenamiento es una carpeta de una máquina. La clasificación de cada dato es documentación, no seguridad: cualquier proceso que conozca la ruta puede leer.

LímiteLas reglas viven en un proyecto que no es una plataforma

El observatorio nació como una plataforma de monitorización, y no es lo que hoy se usa de él. Lo recuperado es lo que sí aporta a esta escala: el registro de dominios, las reglas de gobierno y el mapa. Lo físico (que cada tabla exista y su esquema no haya derivado) existe en el código, pero no se da por vigilado.

LímiteLa obsolescencia mira datos, no código

Una tabla Gold se reconstruye cuando cambian sus entradas. Si cambia una regla, hay que forzar la reconstrucción a mano. Queda escrito en el repositorio.

Había reglas escritas que nadie hacía cumplir, el equivalente a un contrato firmado y guardado en un cajón. Ahora cada dominio comprueba las suyas en su propia suite (el repositorio de ingesta lo hace con una prueba como la de abajo) y el observatorio las repite sobre todos a la vez, incluidas las que solo se ven entre dos: la de cruce de fronteras y la de un Gold que nadie lee, que suele ser un Silver con otro nombre. Todo ello ya encontró cosas en su primera ejecución: una entidad de control sin prefijo de capa y la errata de arriba.

def test_every_flow_declares_a_contract_with_tiered_outputs(path):
    for o in outputs:
        assert o["tier"] in ("bronze", "silver", "gold")
        assert o["entity"].startswith(f"{o['tier']}_")     # el nombre dice la capa
        assert o["path"].startswith(f"feb-scouting/{o['tier']}/")

def test_a_gold_flow_reads_only_silver_or_gold(path):
    for i in inputs:
        assert not i["entity"].startswith("bronze_")
Error realLa ley también se contradecía
Al preparar este trabajo se releyó el documento de gobierno y se vio que una sección permitía construir un Silver a partir del Silver de otro dominio, mientras que otra lo prohibía. Los contratos obligan, pero también hay que mantener la ley. Se corrigió en el mismo cambio, y el documento ahora dice una sola cosa.

7 · Conclusión

A esta escala, el valor de un contrato no es la burocracia: es poder mover el trabajo al sitio que le corresponde sin miedo. Subir la reconstrucción de minutos al productor fue posible porque había una puerta definida por la que servirla, una comparación exacta para demostrar que no cambiaba nada, y un consumidor con pruebas que avisara si algo no encajaba.

Ver el mapa de los datos →← Antes: Los datos: de la FEB a Delta Lake
Fuentes. Actas oficiales y minuto a minuto de la FEB. Datos actualizados por última vez el 4 de octubre de 2026 (último partido incluido).
Contacto. ¿Algo no cuadra, falta algo o hay una idea? Los avisos son bienvenidos por cualquiera de estos canales.
Molokai Lab es un proyecto independiente y no está afiliado a la Federación Española de Baloncesto.