Fire and Forget?
In a tightly coupled system, Service A calls Service B synchronously. If Service B is down, Service A fails. Event-Driven Architecture (EDA) solves this by introducing a Message Broker (like RabbitMQ or Kafka). Service A publishes an event ('UserSignedUp') and forgets about it. The broker ensures it gets delivered to Service B, Service C, and Service D eventually.
Kafka vs. RabbitMQ
RabbitMQ (Smart Broker, Dumb Consumer): Great for complex routing. You can say 'Send this message to the Email Service AND the Audit Service'. It pushes messages to consumers.
Kafka (Dumb Broker, Smart Consumer): acts as a distributed log. It stores messages on disk for days. Consumers 'pull' updates at their own pace. This is better for massive scale (millions of events per second) and for 'replaying' history.
The Challenge of Eventual Consistency
The trade-off for EDA is that your system is no longer instantly consistent. A user might change their profile picture, refresh the page, and still see the old picture because the event hasn't propagated to the Read Model yet. You must design your UI to handle this (e.g., using optimistic UI updates).
Idempotency Pattern
In distributed systems, 'exactly-once' delivery is impossible. You will get duplicate messages. Your consumer code must be idempotent: safely handling the same message twice without corrupting data.