Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

🧩 Schemas — Guide PRO (Web & Dev)

“Schema” = contrat + structure + règles : DB schema, JSON Schema, OpenAPI, GraphQL schema, Avro/Proto, schema.org (SEO), config schemas, migrations, versioning, validation & governance.

1

Concept & vocabulaire

schema vs data, contract, constraints

Fondations
2

DB Schema (SQL)

tables, keys, constraints, namespace

DBProd
3

ORM & Migrations

model schema, migrations, drift, rollback

ORM
4

JSON Schema

validation, required, formats, $ref

Validation
5

OpenAPI / Swagger

contract API REST, codegen, mocks

API
6

GraphQL Schema

types, queries, mutations, federation

GraphQL
7

Avro / Protobuf

schemas event-driven, evolution rules

Events
8

Schema.org (SEO)

JSON-LD, rich snippets, entities

SEO
9

Config Schemas

YAML/JSON validation, policy, IaC

Ops
10

Versioning & compat

backward/forward, semver, deprecation

Gouvernance
11

Pipeline de validation

request → validate → persist → publish

Qualité
12

Outils & patterns

lint, tests de contrat, mocks, CI

Tooling
CONCEPT
  • Schema = description formelle de la forme des données + règles (types, contraintes, invariants).
  • But : réduire l’ambiguïté entre systèmes (FE/BE/DB/Events) et rendre les erreurs détectables tôt.
  • Trois questions : Quoi (structure) / Qui (ownership) / Quand (versioning).
+------------------------------+ | SCHEMA = CONTRAT + RÈGLES | +------------------------------+ DB: tables/constraints API: request/response types Events: message evolution SEO: structured data for bots
Règle d’or : le schema n’est pas la donnée — c’est la règle qui dit si la donnée est valide.
# Exemple “contrat” (humain)
User:
  id: integer (required)
  email: string (required, email format)
  age: integer (optional, min 18)
=> Si tu ne peux pas l’exprimer clairement, le schema manque.
  • Écrire le schema avant l’implémentation (“contract-first”) si l’API est publique / multi-clients.
  • Mettre des exemples (valides & invalides) à côté du schema.
  • Automatiser : lint → tests → génération docs → compat checks.
  • “Schema = documentation approximative” (non testée) → divergence inévitable.
  • Champs “any/opaque” partout → le schema ne protège plus rien.
  • Breaking changes silencieux (renommage champ, changement type).
Un schema non enforced en CI/Runtime devient vite une déco.
KPIPourquoiCible
% endpoints couverts par un schemacontrat explicite100%
Erreurs “validation” vs “500”qualité des inputsvalidation ↑ / 500 ↓
Breaking changes / moisstabilité≈ 0
  1. Chaque objet métier a un contrat (types + règles).
  2. Le contrat est versionné (tag, commit, registry).
  3. Le contrat est testé (CI) et idéalement enforced (runtime).
  4. Tu as une stratégie deprecation (deadline + fallback).
# Pattern utile : “valid/invalid fixtures”
fixtures/
  user.valid.json
  user.invalid_missing_email.json
  user.invalid_age_negative.json
=> tests de contrat simples, lisibles, robustes.
DB SCHEMA
  • En SQL, “schema” peut vouloir dire :
  • 1) La structure : tables/colonnes/types/contraintes/index.
  • 2) Un namespace : ex. PostgreSQL public, auth, reporting.
  • Objectif : garantir des invariants au plus près des données.
+-----------------------------+ | DB SCHEMA | +-----------------------------+ tables -> types keys -> relations constraints -> invariants indexes -> perf contracts
-- PostgreSQL (exemple)
CREATE SCHEMA IF NOT EXISTS auth;

CREATE TABLE auth.users (
  id         bigserial PRIMARY KEY,
  email      text NOT NULL UNIQUE,
  created_at timestamptz NOT NULL DEFAULT now(),
  age        int CHECK (age IS NULL OR age >= 18)
);

-- Contrat : email unique, age>=18, created_at toujours renseigné
  • Mettre les règles critiques en DB : NOT NULL, UNIQUE, FK, CHECK.
  • Éviter que l’appli soit le seul gardien (“business rules only in code” = drift).
  • Nommer et documenter les contraintes : les erreurs DB deviennent lisibles.
  • Contrôler le “schema drift” (prod ≠ migrations) via CI/CD.
  • Tout en NULL + zéro contrainte → la DB ne protège rien.
  • FK absentes “pour la perf” → incohérences, delete orphelins.
  • Types “fourre-tout” (text/json) sans validation → dette de données.
KPICibleAction
Tables sans PK0Ajouter PK / surrogate key
Colonnes critiques NULLables0NOT NULL + backfill
Violations FK/UNIQUE0Fix data + constraints
  1. PK sur chaque table.
  2. FK explicites + index associés si nécessaire.
  3. Contraintes CHECK pour invariants métier simples.
  4. Types précis (éviter text/json “par défaut”).
  5. Migrations idempotentes + rollback strategy.
ORM & MIGRATIONS
  • Un ORM (Django/SQLAlchemy/etc.) a son propre “schema” : models + migrations.
  • Risque : drift (DB réelle ≠ migrations ≠ code).
  • But : garder un seul source of truth et des déploiements reproductibles.
# Exemple mental (peu importe le framework)
Model User:
  email: string unique not null
  created_at: datetime default now
Migration:
  add column / add constraint / add index
Drift typique:
  prod a une colonne en plus ou une contrainte manquante
  • CI : appliquer migrations sur une DB “from scratch” + exécuter tests.
  • Pour prod : migration safe (add column nullable → backfill → set not null).
  • “Expand/Contract pattern” pour changements lourds (renommage, split table, etc.).
  • Monitoring : détecter les migrations lentes/verrouillantes.
Sur les grosses tables : éviter “ALTER type” bloquant, préférer shadow columns + swap.
  • Modifier la DB à la main en prod puis “oublier” de créer la migration.
  • Migration qui fait data + schema sans stratégie (rollback impossible).
  • Renommage champ = breaking change si clients / ETL / BI existent.
  1. Migrations linéaires et reproductibles.
  2. Stratégie rollback (ou forward-only documenté).
  3. Validation “schema drift” automatisée (CI + check prod).
  4. Changements “online” pour tables volumineuses.
JSON SCHEMA
  • JSON Schema décrit la forme d’un JSON : types, required, enum, formats, min/max, regex, etc.
  • Usage : validation d’inputs (API), config, documents, storage JSON, contracts inter-services.
  • Force : validation automatique + réutilisation via $ref.
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "id":    {"type":"integer"},
    "email": {"type":"string","format":"email"},
    "age":   {"type":"integer","minimum":18}
  },
  "required": ["id","email"]
}
# points clés
- required = champs obligatoires
- additionalProperties=false = pas de champs “surprise”
- format=email = validation sémantique minimale
  • Verrouiller l’objet : additionalProperties=false (sinon dérive silencieuse).
  • Factoriser via $ref (User, Money, Address…).
  • Avoir des fixtures “valid/invalid” et tester en CI.
  • Générer documentation + exemples automatiquement.
  • “type: object” sans properties → useless.
  • Tout en anyOf complexes → schema incompréhensible.
  • Formats non testés (ou faux sentiment de sécurité).
  1. Types + required définis.
  2. Règles métier simples intégrées (min/max/enum).
  3. Interdiction de champs inconnus si besoin.
  4. Tests de validation en CI.
OPENAPI
  • OpenAPI décrit une API REST : endpoints, params, auth, request/response schemas, erreurs.
  • Valeur : doc vivante + codegen + mocks + contract tests.
Très utile dès que tu as plusieurs clients (web + mobile + partenaires).
openapi: 3.1.0
info: { title: Users API, version: "1.0.0" }
paths:
  /users/{id}:
    get:
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: integer }
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/User"
components:
  schemas:
    User:
      type: object
      required: [id, email]
      properties:
        id: { type: integer }
        email: { type: string, format: email }
  • Définir des réponses d’erreur standard (400/401/403/404/409/422) avec schema commun.
  • Mettre des examples request/response (très important pour les clients).
  • Bloquer les breaking changes via tooling (diff de spec en CI).
  • Contract tests : serveur conforme à la spec + clients générés compilent.
  • Spec écrite “après” et jamais synchronisée → faux contrat.
  • “schema: {}” partout → doc inutile.
  • Changements sans versionning/deprecation → chaos côté clients.
  1. Chaque endpoint a params + réponses typées.
  2. Auth documentée (bearer, api key, oauth…).
  3. Erreurs standardisées avec schema.
  4. Spec versionnée + diff check en CI.
GRAPHQL SCHEMA
  • GraphQL a un schema central (SDL) : types, champs, queries/mutations, inputs, enums.
  • Contrat puissant : le client sait exactement ce qu’il peut demander.
  • Attention : la perf se gère (N+1, depth/complexity, caching).
type User { id: ID!, email: String!, age: Int }
type Query { user(id: ID!): User }
input CreateUserInput { email: String!, age: Int }
type Mutation { createUser(input: CreateUserInput!): User! }
  • Limiter la complexité : depth/complexity limits + timeouts.
  • Résoudre N+1 (DataLoader pattern, batching).
  • Déprécier proprement : @deprecated(reason: "...") + fenêtre de migration.
  • Registry/federation si multi-services.
  • Schémas trop “DB-like” (exposer tables internes) → couplage fort.
  • Aucune limite → requêtes monstrueuses / DoS applicatif.
  • Champs qui changent de sens sans versioning → clients cassés.
  1. Schema SDL versionné.
  2. Déprecations tracées.
  3. Limits + protections perf.
  4. Tests de contrat (introspection + snapshot).
AVRO / PROTOBUF
  • Pour l’event-driven (Kafka, Pub/Sub, RabbitMQ), le schema devient vital.
  • Protobuf : contrats stricts, codegen, perf (binaire), IDs de champs.
  • Avro : très utilisé en data pipelines (compat rules, schema registry).
  • Problème majeur : schema evolution (backward/forward/full).
// Protobuf (extrait)
message UserCreated {
  int64 id = 1;
  string email = 2;
  int32 age = 3; // optional by presence semantics depending on syntax/version
}
# Règles d’évolution (simplifiées)
- ajouter un champ : OK (si optional / default)
- supprimer un champ : dangereux (préférer "deprecated")
- renuméroter un field id : NON (breaking)
  • Avoir un Schema Registry (même minimal) + validation à la publication.
  • Politique d’évolution : backward-only vs full-compat selon tes consommateurs.
  • Déprécier avant de supprimer, et attendre la fin de fenêtre de migration.
  • Tester compat en CI (ex: “new schema is backward compatible”).
  • Publier des events JSON sans schema → consumers fragiles.
  • Breaking change silencieux → incidents cross-services.
  • Pas d’ownership → “tout le monde change tout”.
  1. Schema versionné + registry.
  2. Compat checks en CI.
  3. Deprecation policy claire.
  4. Consumer tests (canaries) sur nouveaux schémas.
SCHEMA.ORG (SEO)
  • Ici “schema” = données structurées pour moteurs de recherche (souvent en JSON-LD).
  • But : aider Google/Bing à comprendre une page (Article, Product, Organization, FAQ…).
  • Impact : rich snippets, knowledge panels, meilleure compréhension sémantique.
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "Schemas en dev : guide",
  "author": { "@type": "Person", "name": "Guillaume" },
  "datePublished": "2026-02-12"
}
</script>
  • Utiliser JSON-LD (simple à injecter server-side).
  • Rester fidèle au contenu visible (sinon risque de pénalité).
  • Tester régulièrement (données structurées) et versionner les templates.
  • Mettre du schema “fake” (FAQ inventée, reviews fausses) → mauvais plan.
  • Dupliquer/injecter plusieurs JSON-LD incohérents sur la même page.
  1. Type schema.org cohérent (Article/Product/Org…).
  2. Champs essentiels présents.
  3. Pas de divergence contenu vs markup.
CONFIG SCHEMAS
  • Config schema = valider des fichiers de config (YAML/JSON) avant déploiement.
  • Très utile en Ops/IaC : éviter un déploiement cassé pour une clé manquante.
  • Approche : JSON Schema / validation applicative / policies (OPA) selon le niveau.
# Exemple de config "attendue"
app:
  env: "prod"
  port: 8080
  database_url: "postgres://..."
limits:
  rate_per_min: 1200

# Un schema te permet d’empêcher :
# - port string au lieu d’int
# - database_url manquant
# - env hors {dev,staging,prod}
  • Valider en CI (pré-merge) et au démarrage applicatif.
  • Garder des defaults explicites (sinon comportement surprise).
  • Documenter les “breaking config changes” (nouvelle clé requise, clé supprimée).
  • Config “libre” sans validation → incidents “bêtes” en prod.
  • Secrets directement dans les configs versionnées.
  1. Schema de config (même minimal) + validation CI.
  2. Defaults + required clarifiés.
  3. Secrets externalisés (vault/variables d’env).
VERSIONING & COMPAT
  • Le vrai sujet des schemas en prod, c’est l’évolution.
  • Backward compatible : les anciens consumers continuent de fonctionner.
  • Forward compatible : les nouveaux consumers supportent d’anciens messages.
  • Breaking change : nécessite version majeure / endpoint v2 / migration plan.
# REST (typique)
- add field optional => OK
- remove field       => breaking
- change type string->int => breaking
- rename field       => breaking (sauf alias/deprecation)

# DB
- add column nullable => OK
- set NOT NULL sans backfill => risque (breaking en runtime)
- drop column => breaking pour ETL/BI/old code
  • Définir une policy deprecation : annonce + window + date de retrait.
  • Prefer “additive changes” (ajout) plutôt que modifications destructives.
  • Versionner les contrats : tags, releases, registry.
  • Mettre un “compat gate” en CI : refuser un breaking change non versionné.
  • “On change vite, les clients suivront” → non.
  • Deprecation sans date → personne ne migre.
  • Pas d’inventaire des consumers → impossible de savoir qui casse.
  1. Types & champs stables.
  2. Breaking change = version majeure ou endpoint v2.
  3. Deprecation documentée avec deadline.
  4. Compat checks automatisés.
VALIDATION PIPELINE
  • Le schema doit vivre dans le flux : entrée API → validations → DB → events → analytics.
  • Idéal : les erreurs de contrat deviennent des 422/400 propres, pas des 500.
Client
  |
  v
API Gateway / Router
  |
  v
(1) Validate request schema  -----> reject 400/422 (with details)
  |
  v
(2) Business rules + auth
  |
  v
(3) Persist with DB constraints  ---> reject 409/constraint error (mapped)
  |
  v
(4) Publish event with message schema -> registry compat gate
  |
  v
Consumers validate / parse -> store / act
  • Validation “shape” (types/required) tôt, règles métier ensuite.
  • Mapper proprement erreurs DB (unique/fk/check) vers erreurs API.
  • Centraliser les contrats (repo “schemas” / registry) pour éviter la divergence.
  • Tracer : quelles versions de schema sont utilisées en prod.
  1. Validation request/response (au moins request).
  2. DB constraints pour invariants critiques.
  3. Contrat event (schema evolution gérée).
  4. Observabilité des erreurs de validation.
TOOLS & PATTERNS
  • Pattern “contract-first” : spec → mocks → impl → tests → clients.
  • Pattern “contract-tests” : vérifier automatiquement la conformité (producer/consumer).
  • Pattern “schema registry” : un référentiel, un ownership, des règles d’évolution.
# Idées d’automatisation (CI)
- Lint schema (format + conventions)
- Validate fixtures (valid/invalid)
- Diff compat (old vs new)
- Generate docs (HTML/markdown)
- Generate clients (si besoin)
- Publish schema artifact (registry)
# “Contract tests” minimalistes
Given: OpenAPI/JSON Schema
When: run tests against API
Then: responses match schemas + required fields are present
  • Nommer les objets : User vs UserV2 (éviter V2 trop tôt, préférer compat).
  • Éviter les duplications : un schema “User” réutilisé partout via ref.
  • Limiter les “any/unknown” aux zones réellement extensibles.
  • Mettre des “examples” dans les schemas (accélère FE & QA).
  • Docs séparées du schema → drift.
  • Règles d’évolution implicites (“au feeling”).
  • Aucune ownership → personne n’ose dire non aux breaking changes.
  1. Repo/registry des schemas + ownership.
  2. Compat gate en CI.
  3. Fixtures valid/invalid.
  4. Docs auto + exemples.
RÉFÉRENCES
  • Quand tu dis “schema”, précise le contexte : DB / JSON / API / GraphQL / Events / SEO.
  • Le bon réflexe : contract + validation + versioning.
  1. Contrats centralisés + ownership.
  2. Validation automatisée (CI) + erreurs propres (runtime).
  3. Versioning & compat (deprecation policy).
CHEAT-SHEET
SCHEMA (web/dev) = règle qui décrit la structure des données.

DB schema      : tables/colonnes/types/contraintes (+ schema namespace)
JSON Schema    : validation de JSON (required, types, $ref)
OpenAPI        : contrat API REST (request/response/errors)
GraphQL schema : types/queries/mutations (+ deprecations)
Avro/Proto     : contrat events/messages + evolution rules
schema.org     : données structurées SEO (JSON-LD)
SAFE (souvent) :
- ajouter un champ optional
- ajouter une colonne nullable
- ajouter un nouvel endpoint / nouveau type

BREAKING (souvent) :
- supprimer/renommer un champ
- changer type string->int
- rendre obligatoire un champ sans default/backfill
- supprimer une colonne utilisée par ETL/BI
“Pour moi un schema, c’est un contrat formel :
1) il définit les types et contraintes,
2) il est validé automatiquement (CI + runtime),
3) il est versionné avec une politique de compatibilité.
Ça évite les ambiguïtés FE/BE/DB et réduit les incidents de prod.”