Event-Driven Architecture
Events decouple producers from consumers — and quietly hand you ordering, delivery, and schema problems in return.
Event-driven architecture decouples the thing that happened from everything that reacts to it. A service emits a fact. Other services respond on their own schedule.
It is the backbone of most enterprise integration and fintech automation work I have done. It is also where a lot of accidental complexity hides.
Commands and events are not the same
A command is a request to do something. ApprovePayment.
It has one intended handler. It can be rejected.
An event is a statement that something already happened. PaymentApproved.
It has zero or more interested consumers. It cannot be rejected. It is history.
Most cross-service traffic should be events. Commands should mostly stay inside a service.
Why reach for events
- Decoupling. The producer doesn't know who consumes the event. New consumers appear without touching the producer.
- Temporal decoupling. The consumer doesn't have to be online when the event fires. The broker holds it.
- Fan-out. One
InvoiceApprovedcan drive notifications, ledger updates, and reconciliation independently.
What you inherit the moment you add a broker
- Ordering. Most brokers only guarantee order within a partition. Pick partition keys (account id, tenant id) so related events stay ordered.
- Delivery. "At least once" is the realistic default. Every consumer will see duplicates, so consumers must be idempotent.
- Schema. Events outlive the code that produced them. Version the payload and treat it as a public contract.
Lesson. The diagram is the easy part. The cost of events shows up later — in ordering, replays, and schema drift. Design for those on day one, not after the first incident.
Separate transfer from processing
A pattern that keeps showing up: the arrival of something is itself the event.
A file lands. A payment settles. An invoice is approved.
Receiving is one responsibility. Processing is another. Keeping them apart lets each scale independently and makes the pipeline replayable.
Rules of thumb
- Name events as past-tense facts. They are immutable.
- Put enough in the payload that common consumers don't need a callback — but not so much that the event leaks your internal model.
- Assume duplicates and out-of-order delivery. Always.
Architecture Notes
Hard-won lessons and durable patterns from building fintech platforms, enterprise integrations, distributed systems, and AI automation.
Idempotency Patterns
Making operations safe to retry — the single most important property in a payments or integration system. A retried payment must never become a double charge.