Introduction
L'Event Sourcing représente une paradigme architectural fondamental en 2026 pour les systèmes distribués à haute résilience. Au lieu de stocker l'état courant d'une entité (comme dans un modèle CRUD classique), on persiste la séquence immutable d'événements qui l'ont menée à cet état. Imaginez un compte bancaire : plutôt qu'enregistrer un solde final de 1500€, on stocke 'Dépôt de 1000€', 'Retrait de 200€', 'Intérêts de 700€'. Cela offre une traçabilité infinie, une scalabilité horizontale via des projections, et une reconstruction d'état à tout moment.
Pourquoi adopter l'Event Sourcing aujourd'hui ? Dans un monde de microservices et d'IA générative, les audits réglementaires (RGPD, finance) exigent une histoire complète des changements. Il s'intègre parfaitement au CQRS (Command Query Responsibility Segregation) pour séparer écriture et lecture, boostant les performances jusqu'à 10x sur des workloads OLTP. Ce tutoriel avancé, sans code, vous guide de la théorie aux pièges avancés, avec des cas concrets comme un système bancaire ou e-commerce. À la fin, vous saurez modéliser des agrégats complexes et scaler en production. (148 mots)
Prérequis
- Maîtrise du Domain-Driven Design (DDD) : agrégats, entités, valeur objects.
- Connaissances en CQRS et Event-Driven Architecture.
- Expérience avec des bases de données : SQL/NoSQL, idéalement event stores comme Kafka ou Axon.
- Compréhension des patterns de concurrence : optimistic locking, versioning.
- Familiarité avec les principes d'immutabilité et idempotence.
Fondamentaux de l'Event Sourcing
L'Event Sourcing repose sur trois piliers : immutabilité, atomicité et replay.
- Immutabilité : Les événements sont append-only, jamais modifiés. Analogie : un journal de bord maritime où chaque entrée est gravée dans la pierre.
- Atomicité : Chaque événement représente un changement d'état atomique, validé par les règles métier.
- Replay : Pour obtenir l'état courant, on 'rejoue' tous les événements séquentiellement sur un agrégat.
CompteCree(1000€), DepotEffectue(500€), RetraitEffectue(200€). État à t=3 : solde=1300€ via réduction : 1000 +500 -200. Avantage : audit temporel précis, impossible avec un simple UPDATE solde=1300.
Différence vs CRUD : CRUD mutate l'état (UPDATE users SET balance=1300), perdant l'historique. Event Sourcing scale via sharding par stream d'événements.
Modélisation des événements et agrégats
Un événement est un fait passé immutable : Event { type: string, data: object, timestamp: Date, aggregateId: UUID, version: int }.
Règles de modélisation :
- Granularité fine : Un événement = une décision métier unique.
- Contexte borné (Bounded Context) : Événements scoped par domaine DDD.
- Versioning : Incrémenter pour détecter les conflits.
Étude de cas : E-commerce. Agrégat
Commande :| Événement | Données | Effet sur état |
|---|---|---|
| ----------- | --------- | --------------- |
CommandePasse | {produits: [...], total: 250€} | Statut='EnAttentePaiement' |
PaiementConfirme | {montant:250€, ref:'PAY123'} | Statut='Payee', stock-=quantités |
LivraisonEnvoyee | {tracking:'TRK456'} | Statut='Expediee' |
Piège : Éviter les événements trop larges comme
CommandeModifiee ; préférez ProduitAjoute, ProduitSupprime pour traçabilité.Event Store et gestion de la persistance
L'Event Store est une base append-only partitionnée par stream (un par agrégat instance). Structure typique : table events avec colonnes aggregate_id, sequence, event_type, payload (JSON).
Queries avancées :
- Lecture stream :
SELECT * FROM events WHERE aggregate_id=? ORDER BY sequence. - Position temporelle : Index sur timestamp pour CDC (Change Data Capture).
Scalabilité : Sharding horizontal par aggregate_id. Pour 1M événements/jour, Kafka comme Event Store excelle avec compaction.
Exemple banque : Stream compte-uuid-123 : 1000 événements/an. Reconstruction : foldLeft(EtatInitial, events.map(applyEvent)). Performance : O(n) mais n petit via snapshots (voir plus loin).
Intégration CQRS et Projections
Event Sourcing s'allie au CQRS : Commands mutent l'Event Store (côté écriture), Queries lisent des vues matérialisées (côté lecture).
Projections : Processus asynchrone transformant événements en vues optimisées.
- Synchronous : Pour faible latence (projet en mémoire).
- Asynchrone : Via Kafka Streams ou Apache Flink pour scalabilité.
Framework de projections :
- Subscribe au topic events.
- Appliquer événement à la vue :
on(PaiementConfirme) { updateVueStock() }. - Persister vue en DB read-optimized (Elasticsearch).
Cas e-commerce : Projection
StockVue : incrémentée par CommandePasse, décrémentée par Annulation. Résultat : queries O(1) vs replay O(n).Gestion avancée : Snapshots, Concurrence et Temporal Queries
Pour n>10k événements, snapshots : États périodiques stockés (toutes 1000 events). Reconstruction : snapshot + delta events.
Concurrences :
- Optimistic : Vérifier version avant append ; reject si conflit.
- Pessimistic : Locks distribués (via Redis), rare en Event Sourcing.
Temporal Queries : "État à date X ?" → Replay jusqu'à timestamp X.
Exemple : Banque, conflit dépôt/retrait simultané → reject le second avec VersionConflictError, client retry.
Bonnes pratiques
- Événements enrichis : Inclure
userId,correlationIdpour traçabilité. - Idempotence : Commands avec
commandIdunique ; ignorer si déjà appliqué. - Snapshots intelligents : Fréquence adaptative (log(n) events) + compression LZ4.
- Projections multiples : Une par use-case (audit, analytics, UI).
- Monitoring : Métriques lag projections, taille streams ; alertes >1h.
- Migration : Événements upcasting pour évolution schéma sans downtime.
Erreurs courantes à éviter
- Événements anémiques : Données incomplètes → impossible de reconstruire. Solution : Toujours full context.
- Réplay coûteux : Pas de snapshots → timeouts. Limitez à 5000 events/stream.
- Couplage fort projections : Échec d'une projection bloque les autres. Utilisez dead-letter queues.
- Ignore versioning : Concurrence perdue → corruption. Toujours incrémenter et valider.
Pour aller plus loin
- Livres : "Implementing Domain-Driven Design" de Vaughn Vernon ; "Event Storming" de Alberti.
- Outils : Axon Framework, EventStoreDB, Kafka + Debezium.
- Études : Uber (Schemaless Event Store), Netflix (pour analytics).
- Formations Learni : Architecture Event-Driven pour hands-on DDD+CQRS.
- Conférences : QCon, DDD Europe 2026.