image de chargement
Retour au glossaire

Event Sourcing

Pattern architectural stockant l'état d'une application comme séquence d'événements immuables, permettant audit complet et reconstitution temporelle.

Mis à jour le 9 janvier 2026

L'Event Sourcing est un pattern architectural qui consiste à persister l'état d'une application non pas comme un snapshot unique, mais comme une séquence chronologique d'événements immuables. Chaque modification est capturée sous forme d'événement descriptif qui relate ce qui s'est passé. Cette approche transforme la base de données en journal d'audit complet, où l'état actuel est dérivé en rejouant tous les événements historiques.

Fondements de l'Event Sourcing

  • Événements immuables : chaque changement d'état est enregistré comme un fait historique qui ne peut être modifié
  • Source de vérité : le journal d'événements (event store) devient la source autoritaire, l'état actuel étant une projection calculée
  • Traçabilité totale : conservation de l'historique complet avec contexte temporel et causalité des changements
  • Reconstitution temporelle : possibilité de reconstruire l'état du système à n'importe quel moment du passé

Avantages stratégiques

  • Audit et conformité : historique inaltérable répondant aux exigences réglementaires (GDPR, SOX, finance)
  • Debugging avancé : reproduction exacte des bugs en rejouant les événements dans les mêmes conditions
  • Projections multiples : création de vues matérialisées optimisées pour différents cas d'usage à partir des mêmes événements
  • Évolution du modèle : ajout de nouvelles fonctionnalités en rejouant l'historique avec une logique enrichie
  • Scalabilité en lecture : séparation CQRS naturelle avec réplication asynchrone des projections

Exemple concret : Système bancaire

Considérons un compte bancaire où au lieu de stocker uniquement le solde actuel, on enregistre chaque transaction comme événement :

bank-account-events.ts
// Définition des événements
interface AccountEvent {
  eventId: string;
  accountId: string;
  timestamp: Date;
  version: number;
}

interface AccountOpened extends AccountEvent {
  type: 'AccountOpened';
  initialDeposit: number;
  currency: string;
}

interface MoneyDeposited extends AccountEvent {
  type: 'MoneyDeposited';
  amount: number;
  source: string;
}

interface MoneyWithdrawn extends AccountEvent {
  type: 'MoneyWithdrawn';
  amount: number;
  destination: string;
}

// Agrégat reconstruisant l'état
class BankAccount {
  private balance: number = 0;
  private status: 'open' | 'closed' = 'open';
  private version: number = 0;
  private id: string = '';

  // Reconstruction de l'état par replay
  rehydrate(events: AccountEvent[]): void {
    events.forEach(event => this.apply(event));
  }

  private apply(event: AccountEvent): void {
    switch (event.type) {
      case 'AccountOpened':
        this.balance = event.initialDeposit;
        this.status = 'open';
        break;
      case 'MoneyDeposited':
        this.balance += event.amount;
        break;
      case 'MoneyWithdrawn':
        this.balance -= event.amount;
        break;
    }
    this.version = event.version;
  }

  // Commande générant un événement
  withdraw(amount: number): MoneyWithdrawn {
    if (this.balance < amount) {
      throw new Error('Insufficient funds');
    }
    return {
      type: 'MoneyWithdrawn',
      eventId: crypto.randomUUID(),
      accountId: this.id,
      timestamp: new Date(),
      version: this.version + 1,
      amount,
      destination: 'ATM'
    };
  }

  getBalance(): number {
    return this.balance;
  }
}

Mise en œuvre technique

  1. Modéliser les événements métier : identifier les faits immuables significatifs (nommage au passé : 'OrderPlaced', 'PaymentProcessed')
  2. Choisir un event store : base spécialisée (EventStoreDB, Apache Kafka) ou adaptation d'une DB existante (PostgreSQL avec tables append-only)
  3. Implémenter les agrégats : objets métier reconstruisant leur état en rejouant les événements avec gestion optimiste de concurrence
  4. Créer des projections : vues matérialisées calculées asynchronement pour les requêtes, mises à jour via event handlers
  5. Gérer les snapshots : sauvegardes périodiques de l'état pour accélérer le rechargement des agrégats volumineux
  6. Mettre en place le versioning : stratégie d'évolution des événements (upcasting) pour compatibilité ascendante

Conseil d'architecture

Combinez Event Sourcing avec CQRS pour séparer clairement les écritures (événements) des lectures (projections). Utilisez des snapshots tous les N événements (ex: 100) pour éviter de rejouer des milliers d'événements à chaque chargement. Implémentez un mécanisme de projection rebuild pour régénérer les vues en cas de bug ou d'ajout de fonctionnalité.

Outils et frameworks associés

  • EventStoreDB : base de données spécialisée pour Event Sourcing avec projections natives
  • Axon Framework : framework Java/Spring complet pour CQRS et Event Sourcing
  • Marten : bibliothèque .NET transformant PostgreSQL en event store avec projections LINQ
  • Apache Kafka : plateforme de streaming distribuée utilisable comme event log persistant
  • Eventsauce : bibliothèque PHP légère pour Event Sourcing avec générateur de code
  • Equinox : toolkit F#/.NET pour Event Sourcing avec support CosmosDB et DynamoDB

L'Event Sourcing apporte une valeur métier significative dans les domaines nécessitant traçabilité, conformité et analyse temporelle (finance, e-commerce, healthcare). Bien que plus complexe qu'une architecture CRUD traditionnelle, il offre une flexibilité d'évolution exceptionnelle et résout naturellement des problèmes complexes de synchronisation et d'audit. L'investissement initial se rentabilise particulièrement sur les systèmes à longue durée de vie avec des exigences réglementaires strictes.

L'argentestdéjàsurlatable.

En 1 heure, découvrez exactement combien vous perdez et comment le récupérer.