L’architecture orientée événements est un style de conception où les services émettent des faits immuables (événements) et les consommateurs réagissent seuls. La précision que les pages des éditeurs escamotent tient en deux mots : un événement est un fait immuable, au passé — OrderPlaced, pas PlaceOrder — et le producteur ne sait pas qui réagit, et ne s’en soucie pas. Cette indifférence, c’est l’architecture : on ajoute, retire ou casse des consommateurs sans que le producteur change une ligne, ce qui est le découplage au sens le plus littéral. Et l’EDA est un spectre, pas une religion — un simple webhook est orienté événements ; une plateforme de streaming aussi ; la plupart des systèmes sains sont hybrides.
Points clés
| Question | Réponse |
|---|---|
| Un événement est | Un fait immuable, au passé — les consommateurs peuvent réagir, jamais refuser |
| Événement ≠ commande | Des faits diffusés à qui veut l’entendre vs. des impératifs adressés à un seul handler |
| La règle de décision | Travail du producteur terminé avant les réactions → événements ; l’appelant a besoin de la réponse → requête-réponse |
| Les trois variantes | Notification · event-carried state · event sourcing (un choix de stockage) |
| La facture permanente | Consommateurs idempotents, ID de corrélation, UX pensée pour la cohérence à terme |
Un fait, plusieurs réactions
// JavaScript — Cloud Code (cloud/main.js)
// Everyday EDA: the write IS the event; consumers react independently
Parse.Cloud.afterSave('Order', async (req) => {
const order = req.object;
const becamePlaced = order.get('status') === 'placed' &&
req.original?.get('status') !== 'placed';
if (!becamePlaced) return;
// Consumers of one fact — none knows about the others:
await Parse.Cloud.httpRequest({ // fulfillment system (webhook)
method: 'POST', url: process.env.FULFILL_WEBHOOK,
body: { event: 'order.placed', id: order.id },
});
await enqueueConfirmationEmail(order); // async job queue
// Live Query pushes the change to every open dashboard automatically
}); // Flutter / Dart — Back4app Flutter SDK
// The client as event consumer: subscribe to facts, react on arrival
final orders = QueryBuilder<ParseObject>(ParseObject('Order'))
..whereEqualTo('status', 'placed');
final sub = await LiveQuery().client.subscribe(orders);
sub.on(LiveQueryEvent.create, (order) => showNewOrder(order));
// Nobody called this screen — it REACTED to an event, like every
// other consumer of "order placed": fulfillment, email, analytics. // iOS / Swift — Back4app Swift SDK
// The client as event consumer: subscribe to facts, react on arrival
let orders = Order.query("status" == "placed")
let sub = try await orders.subscribe()
sub.handleEvent { _, event in
if case .created(let order) = event { showNewOrder(order) }
}
// Nobody called this screen — it REACTED to an event, like every
// other consumer of "order placed": fulfillment, email, analytics. // Android / Kotlin — Back4app Android SDK
// The client as event consumer: subscribe to facts, react on arrival
val orders = ParseQuery.getQuery<ParseObject>("Order")
orders.whereEqualTo("status", "placed")
val sub = ParseLiveQueryClient.Factory.getClient().subscribe(orders)
sub.handleEvent(SubscriptionHandling.Event.CREATE) { _, order ->
showNewOrder(order)
}
// Nobody called this screen — it REACTED to an event, like every
// other consumer of "order placed": fulfillment, email, analytics. Un fait — une commande client a été passée — et quatre consommateurs, dont aucun ne connaît les autres : un système de préparation des commandes prévenu par webhook, un job d’e-mail mis en file d’attente, l’analytics qui compte, des dashboards mis à jour par un abonnement en direct. Ajouter un cinquième consommateur ne change rien en amont. Tout l’argumentaire tient dans une seule sauvegarde.
Le vocabulaire, démêlé
Le chaos terminologique des résultats de recherche, résolu en un tableau — trois types de messages classés par intention, pas par transport :
| Commande | Événement | Requête | |
|---|---|---|---|
| Grammaire | Impératif : ShipOrder | Passé : OrderShipped | Interrogatif |
| Destinataire | Un seul handler | Quiconque s’est abonné | Un seul répondant |
| Peut être refusé | Oui | Non — c’est déjà arrivé | n/a |
| Couplage | L’émetteur connaît le handler | Le producteur ne connaît personne | L’appelant attend |
L’avertissement de Fowler mérite d’être repris : méfiez-vous de la commande passive-agressive — un « événement » que le producteur émet tout en exigeant en secret qu’un consommateur précis agisse. Si le flux casse quand ce consommateur ne répond pas, c’était une commande depuis le début, et l’appeler événement n’a fait que cacher le couplage. (Les termes d’infrastructure — broker, routeur, bus, canal, topic (sujet) — sont des quasi-synonymes pour la boîte du milieu ; l’article sur le pub/sub détaille cette mécanique, dont l’EDA est l’architecture qui généralise.)
Orienté événements vs. requête-réponse
| Requête-réponse | Orienté événements | |
|---|---|---|
| Couplage temporel | L’appelant attend — l’appelé doit être disponible | Fire-and-forget — les consommateurs rattrapent leur retard |
| La réponse | Renvoyée à l’appelant | Il n’y a pas de réponse, seulement des réactions |
| Mode de défaillance | Erreur immédiate et visible | Résilient — et cohérent à terme |
| Débogage | Une seule pile d’appels | ID de corrélation à travers les sauts |
| Adapté à | Lectures, connexions, paiements — tout ce dont l’appelant a besoin | Des faits aux consommateurs indépendants |
La règle en une phrase : si l’appelant a besoin du résultat pour continuer, requête-réponse ; si le travail du producteur est terminé avant que la moindre réaction commence, événements. Passer la commande exige une réponse synchrone (« ça a marché ? ») ; tout ce qui suit — e-mail, préparation, analytics — ce sont des réactions à un fait, et c’est pourquoi les vrais systèmes sont hybrides par conception, pas par compromis.
Les trois variantes de Fowler — et la vraie place de l’event sourcing
| Pattern | L’événement porte | Consommateurs | Trade-off |
|---|---|---|---|
| Event notification | Un ID et presque rien d’autre | Rappellent pour les détails | Simple ; le trafic de rappels recrée du couplage |
| Event-carried state transfer | Tout l’état pertinent | Gardent des copies locales | Pas de rappels ; duplication et données périmées |
| Event sourcing | Est le système de référence | Reconstruisent l’état par rejeu | Audit parfait ; un engagement de stockage lourd |
La distinction qui économise des réunions : l’event sourcing, c’est la façon dont un système stocke ses données ; l’EDA, la façon dont les systèmes communiquent. Les deux se combinent, mais aucun n’exige l’autre. Encore une frontière que les éditeurs brouillent : la livraison pub/sub oublie — un abonné arrivé en retard rate ce qui a été émis avant lui — alors que le streaming (le log ordonné à la Kafka) se souvient et laisse les consommateurs rejouer depuis n’importe quel point ; choisissez selon que l’historique fait partie du produit ou non.
Chorégraphie vs. orchestration
| Chorégraphie (native de l’EDA) | Orchestration | |
|---|---|---|
| Coordination | Les services réagissent aux événements des autres | Un coordinateur commande chaque étape |
| Où vit le workflow | Nulle part explicitement — il émerge | En un seul endroit visible et débogable |
| Couplage | Minimal | L’orchestrateur connaît tout le monde |
| Gestion des échecs | Événements compensatoires, distribués | Retry et logique d’erreur centralisés |
La règle miroir, partagée avec l’article sur l’orchestration : orchestrez quand quelqu’un doit être responsable du résultat d’un workflow ; chorégraphiez quand les producteurs ne se soucient réellement pas de la suite. Les longues transactions métier entre services prennent dans les deux cas la forme d’une saga — des transactions locales enchaînées par des événements ou par un orchestrateur, annulées par des actions compensatoires plutôt que par un rollback.
L’EDA au quotidien — sans broker
La section que les centres d’architecture n’écrivent jamais : la plupart des développeurs d’applications pratiquent déjà des patterns orientés événements sans le moindre broker de messages en vue. Un trigger beforeSave/afterSave est un consommateur d’événements de modification de données. Un webhook est un événement qui franchit les frontières entre entreprises en simple HTTP. Une live query est du pub/sub dont les abonnés sont des clients. Un job en arrière-plan mis en file par un trigger est un événement qui déclenche du travail asynchrone. Les onglets de code ci-dessus montrent exactement ce stack — l’écriture est l’événement, le trigger est le routeur, et les consommateurs sont un webhook, une file d’attente et un abonnement. Les brokers dédiés (Kafka, RabbitMQ, NATS — avec CloudEvents comme enveloppe standard) justifient leur poids opérationnel quand le volume d’événements, le rejeu et les contrats entre équipes l’exigent ; l’architecture commence bien plus tôt, et la question « ai-je besoin d’un broker ? » se tranche généralement d’elle-même : pas encore.
Cas d’usage courants
- Flux de commande et de paiement — un fait, plusieurs services métier : le pipeline e-commerce type.
- Intégration entre systèmes — des services détenus par des équipes différentes qui réagissent sans appels directs ni déploiements communs.
- Fonctionnalités temps réel — dashboards, fils d’actualité et présence comme consommation d’événements côté client.
- Charges en pics — des files d’attente qui absorbent les rafales pour que les consommateurs les vident à leur rythme.
- Audit et rejeu — des logs de streaming où « ce qui s’est passé, dans l’ordre » est le produit lui-même.
Faut-il passer à l’orienté événements ? Matrice de décision
| Situation | Orientation |
|---|---|
| Un fait, plusieurs consommateurs indépendants | Événements — leur terrain de prédilection |
| L’appelant a besoin de la réponse pour continuer | Requête-réponse, sans complexe |
| Workflow avec un responsable et un SLA | Orchestration — commandez les étapes |
| Réactions au sein d’une app (e-mail à l’inscription) | Triggers + jobs — l’EDA au quotidien |
| Notifications entre entreprises | Webhooks |
| Streams à fort volume, rejouables, multi-équipes | Un vrai broker — il l’a mérité |
Limites et trade-offs
- Le débogage perd la pile d’appels. Une requête qui se disperse en cinq sauts asynchrones n’est traçable que par des ID de corrélation propagés depuis le premier événement — les ajouter après coup est pénible ; câblez-les dès le premier jour.
- La cohérence à terme remonte jusqu’à l’interface. L’utilisateur modifie son profil et l’écran suivant affiche l’ancien nom ; soit vous concevez l’UX en conséquence, soit vous gardez ce chemin synchrone.
- Les doublons font partie du contrat. La livraison at-least-once rend les consommateurs idempotents obligatoires — le même contrat que celui des files d’attente, parce que c’est la même mécanique.
- Les schémas évoluent sous les pieds des consommateurs. Les événements sont des contrats avec des abonnés inconnus : uniquement des changements additifs, des topics versionnés pour les ruptures et des lecteurs tolérants partout.
- Les workflows émergents se cachent. Une chorégraphie pure signifie que personne ne peut montrer du doigt le processus métier ; quand les auditeurs ou les ingénieurs d’astreinte en ont besoin, ajoutez l’orchestrateur.
Les patterns orientés événements sur Back4app
Back4app est une plateforme open-source de Backend as a Service (BaaS) qui combine une base de données gérée, des API REST et GraphQL générées automatiquement, l’authentification, le stockage de fichiers et des fonctions serverless avec Cloud Code. La section sur l’EDA au quotidien, c’est sa liste de fonctionnalités lue comme une architecture : chaque sauvegarde est un événement, les triggers afterSave sont des consommateurs côté serveur avec tout l’écosystème JavaScript, les Live Queries diffusent les faits vers les clients via des WebSockets gérés, les webhooks les portent vers des systèmes externes et les jobs en arrière-plan absorbent les réactions lentes — les onglets de code montrent la boucle complète à partir d’une seule sauvegarde de commande. Les disciplines sur lesquelles insiste cet article restent les vôtres (after-hooks idempotents, raisonnement au passé, synchrone là où l’appelant a besoin d’une réponse), tandis que l’infrastructure de type broker — fan-out, livraison, parcs de connexions — arrive sous forme de comportement de la plateforme, et passer plus tard à un broker de streaming dédié viendra s’ajouter à cette architecture, sans la réécrire.
Questions fréquentes
Qu'est-ce que l'architecture orientée événements en termes simples ?
Les composants annoncent qu'il s'est passé quelque chose — un événement — au lieu de s'appeler les uns les autres, et chaque composant intéressé réagit à son propre rythme. Une émission de radio plutôt qu'un coup de téléphone : le travail de l'émetteur s'arrête à l'annonce, et les auditeurs vont et viennent sans que l'émetteur change quoi que ce soit.
Quelle est la différence entre un événement et une commande ?
L'intention. Une commande est un impératif adressé à un seul destinataire, qui peut la refuser — ShipOrder. Un événement est un fait au passé diffusé à qui veut l'entendre — OrderShipped. Le piège, c'est la « commande passive-agressive » : un événement qui attend en secret qu'un consommateur précis agisse, autrement dit une commande déguisée.
Quelle est la différence entre l'orienté événements et le modèle requête-réponse ?
Le couplage dans le temps. Le modèle requête-réponse est synchrone — l'appelant attend, a besoin de la réponse et échoue si l'appelé est indisponible. Les événements sont fire-and-forget — résilients et découplés, mais cohérents à terme. La règle : si l'appelant a besoin du résultat pour continuer, requête-réponse ; si le travail du producteur est terminé avant que les réactions commencent, événements.
Quelle est la différence entre l'EDA et le pub/sub ?
Le niveau. Le pub/sub est un pattern de messagerie — un mécanisme de livraison, des publieurs vers des topics, des topics vers des abonnés. L'EDA est le style d'architecture qui s'appuie généralement dessus, avec les files d'attente et les streams. Le pub/sub, c'est la plomberie ; l'orienté événements, la philosophie de conception que cette plomberie sert.
Que sont l'event notification, l'event-carried state transfer et l'event sourcing ?
Les trois patterns distincts que Fowler repère sous un même nom. Notification : des événements minces, les consommateurs rappellent pour obtenir les détails. State transfer : les événements portent les données complètes, les consommateurs en gardent des copies locales. Sourcing : un choix de persistance — stocker chaque changement comme un événement et reconstruire l'état par rejeu. Le troisième décrit comment un système stocke ses données, pas comment les systèmes communiquent.
Quelle est la différence entre chorégraphie et orchestration ?
Chorégraphie : les services réagissent aux événements des autres, sans cerveau central — découplage maximal, mais le workflow n'existe explicitement nulle part. Orchestration : un coordinateur commande chaque étape — visible et débogable, au prix d'un point de couplage central. La règle : orchestrez quand quelqu'un doit être responsable du résultat ; chorégraphiez quand les producteurs ne se soucient réellement pas de la suite.
Comment gérer les événements en double et dans le désordre ?
Par conception, pas par espoir : les brokers livrent en at-least-once, donc les consommateurs doivent être idempotents — dédupliquez sur l'ID de l'événement, ou écrivez des handlers dont la répétition est sans effet (« passer le statut à expédié », jamais « basculer »). L'ordre n'est garanti que par partition ou par clé ; une architecture qui exige un ordre global se bat contre son propre transport.
Quand utiliser l'architecture orientée événements ?
Quand un même fait a plusieurs consommateurs indépendants, quand la charge est irrégulière et qu'un tampon aide, quand des systèmes doivent s'intégrer sans se connaître, ou quand une piste d'audit des changements a de la valeur. À éviter : le CRUD simple, les lectures, les opérations qui exigent une cohérence forte immédiate et les équipes sans appétit pour les systèmes distribués.