Question presented to candidate: "A new requirement arrives: every time an order is placed, a fraud-check service must also be notified — on top of the existing email and inventory services that already react to it. Does the order-placement code need to change to support this?"
What a strong answer should cover:
- Event-driven architecture structures a system around components emitting events and other components subscribing to them, rather than the emitting component directly calling every interested party by name — Node's built-in
EventEmitter(covered fully in its own dedicated question) is the standard, idiomatic implementation of this pattern within a single process. - 📌 Verified, not just described: a real publisher function with three independent subscribers, then a fourth subscriber added later, required zero changes to the publisher itself — confirmed directly, the fourth subscriber started receiving events immediately upon registration, with no modification to the code that emits them.
- This is the concrete, direct answer to the prompt: no, the order-placement code does not need to change to add a fraud-check subscriber — it only needs to
.on()the existing event, exactly as demonstrated. - The core benefit is decoupling: the publisher has no knowledge of who is listening, how many subscribers exist, or what they each do — verified directly by the fourth subscriber's addition requiring no publisher-side change at all. This is a different, looser coupling than a publisher directly calling
emailService.send(),inventoryService.decrement(), andfraudCheck.screen()explicitly by name. - A precise answer names the trade-off honestly: this decoupling makes the overall flow harder to trace by reading the publisher's code alone — understanding everything that happens when an order is placed requires knowing every subscriber registered somewhere else in the codebase, which a direct, explicit call list would show in one place.
- At a distributed-systems scale, the same underlying idea extends beyond a single process via a message broker (Kafka, RabbitMQ, or the
BullMQ-style job queue covered in its own dedicated question) — the pattern is identical (a publisher emits, independent consumers subscribe), but the transport becomes a network-level broker instead of an in-processEventEmitter.
Clarifying questions expected:
- "Is this a single-process, in-memory pattern (EventEmitter), or does it need to span multiple services/processes (a message broker)?" — the pattern is conceptually the same; the mechanism differs significantly.
- "Is the concern adding a new subscriber, or understanding why an existing flow behaves the way it does?" — decides which direction of the demonstration matters most.
Code / implementation expected: Yes — the real, direct demonstration of adding a fourth subscriber with zero publisher changes is the concrete, convincing proof of the core decoupling benefit, not a description of it.