Why it matters
In a request-driven design, the system that records a payment must also call the notification service, the fraud system, the analytics store and anyone else who cares, and wait for each. Every new consumer means changing the payment system. In an event-driven design, the payment system publishes one fact, “payment 123 completed”, and anyone interested subscribes. The producer does not need to know who is listening, and a slow consumer cannot slow down the payment.
The model explained
An event records something that has already happened, with the details needed to act on it. A request asks for something to happen and expects an answer. Events are published to a log: an ordered, durable sequence that consumers read at their own pace and can replay from any point.
One event, many consumers
Text description
A core or payment service writes a change and an outbox record together. A relay publishes the outbox record to a partitioned event log. Notifications, fraud scoring, analytics and read models each consume the log independently.
- Core or payment service to Outbox table (same database): one transaction
- Outbox table (same database) to Event log (partitioned): relay
- Event log (partitioned) to Notifi- cations
- Event log (partitioned) to Fraud scoring
- Event log (partitioned) to Analytics
- Event log (partitioned) to Read models
Designing events
A good event describes a business fact in the past tense, such as payment completed or mandate cancelled, and carries enough detail that most consumers need not call back for more. Its structure is registered in a shared schema registry, so producers and consumers agree on the format. Changes are additive where possible: new fields can be added, but existing ones are not removed or renamed without a new event version. Each event carries a unique identifier, the time it happened and the identifier of the thing it describes, which together make idempotent processing and tracing possible.
Event sourcing and CQRS
Event sourcing goes further: the events themselves are the record, and the current balance is calculated by replaying them. Banking has always worked a little like this, since a ledger is a list of postings. CQRSCommand query responsibility segregation. A design that handles writes and reads with separate models, so each can be optimised on its own. (command query responsibility segregation) separates the model that accepts changes from the models that answer questions. A mobile app’s “recent transactions” screen can read from a fast read model built from events, instead of querying the core.
The outbox pattern and change data capture
The hardest practical problem is keeping the database and the event log in step. If a service updates its database and then publishes an event, a crash between the two leaves them disagreeing. The outbox pattern writes the change and a record of the event in the same database transaction; a separate relay then publishes outbox records to the log and marks them sent. Change data capture (CDCChange data capture. Streaming every change made to a database so other systems can react to it or keep a copy up to date.) achieves a similar result by reading the database’s own change log.
The outbox pattern
Text description
- Service to Database: Change + outbox row
- Relay to Database: Read new rows
- Database to Relay: Rows (response)
- Relay to Event log: Publish
- Relay to Database: Mark sent
- Event log to Consumer: Deliver
Exactly once, ordering and partitions
Some products promise exactly-once delivery. That promise holds inside the product; once an event causes a change in another system, such as a ledger, the consumer still needs its own idempotency check, usually by recording each event’s identifier. Ordering is guaranteed only within a partition, so events that must stay in order, such as every event for one account, are sent to the same partition by using the account number as the key.
How it plays out in Indian banking
Events suit the work that surrounds a payment rather than the payment itself: alerts to customers, fraud features, analytics, audit trails and read models for apps. The core posting stays a request with a definite answer. The scale makes the decoupling valuable. At about 791 million a day1Business Standard. UPI sets new record at 24.51 bn transactions in Aug, value at ₹29.82 trn. As of 31 August 2026. across the UPIUnified Payments Interface. NPCI's real-time system for paying from a bank account with a UPI ID, QR code or phone number, through apps on a phone. system, a bank cannot afford for a slow analytics job to hold up payments. The events also form an audit trail: an ordered, time-stamped record of what each system saw and when.
Trade-offs
| Choice | You gain | You give up |
|---|---|---|
| Publish events instead of calling consumers | New consumers without changing the producer | No immediate confirmation that a consumer acted |
| Durable, replayable log | Consumers can rebuild state and recover from bugs | Storage, retention rules and a platform to run |
| Read models built from events | Fast screens that do not load the core | Read models lag behind by seconds or more |
| Event sourcing | Full history and easy audit | Complex queries and careful handling of changes to event formats |
Failure modes
- Lost events when a service writes to its database and publishes separately, without an outbox or CDC.
- Duplicate effects when consumers assume each event arrives exactly once.
- Out-of-order processing when related events land in different partitions.
- Silent lag, where a consumer falls hours behind and no alert fires because nothing has technically failed.
- Format breakage when a producer changes an event’s structure and old consumers cannot read it.
When to use it, and when to avoid it
Use events when several systems need to react to the same fact, when consumers can tolerate a short delay, or when an ordered history is valuable in itself. Avoid them for the step that must give the customer a definite yes or no, such as authorising a debit. That step is better as a request with a clear answer, followed by an event that tells everyone else.
Questions for a design review
- Which step must give a definite answer, and which steps can react later to an event?
- How does the producer guarantee that a database change and its event never disagree?
- How does each consumer detect and ignore an event it has already processed?
- Which events must stay in order, and what partition key keeps them together?
- How far behind can each consumer fall before someone is alerted?