0% completed
Requests and Events
On This Page
Requests
Events
One Scan, Three Readers
The Deciding Question
Requests and Events in One Flow
What Each Choice Costs
Using This in an Interview
Key Takeaways
Practice Questions
There are two ways for one service to involve another service. It can ask a question and wait for the answer (a request), or it can announce that something has happened and continue with its own work (an event). Nearly every connection between two backend services is one of these two, and the choice decides who waits, which services fail together, and which services can change without asking anyone.
Consider a parcel delivery company. At 09:14 a driver scans parcel P-58210 at the van door, and the parcel is now out for delivery. At 09:20 the customer opens the tracking page to see where the parcel is. Both moments concern the same parcel and the same status, yet they call for different kinds of communication.
The rest of this page follows that one parcel from the scan to the customer's screen and shows how to tell the two kinds apart.
Requests
A request is a message that asks another service to return something or do something, and the sender waits for the reply before it continues. When the customer opens the tracking page, the page sends GET /parcels/P-58210/status to the tracking service. The page cannot show anything useful until the answer arrives.
A request ties the two services together in time. Both must be running at the same moment, and the caller is only as fast as the service it calls. If the tracking service answers in 40 ms, the page waits 40 ms. If the tracking service takes 4 seconds, the customer watches a loading indicator for 4 seconds.
Availability multiplies along a chain of requests. Here is a simple example. The tracking page calls the tracking service, which calls the depot service, which calls the route service, and each of the three is available 99.9% of the time. The chain works only when all three work, so its availability is 0.999 x 0.999 x 0.999, or about 99.7%. A 30-day month has 43,200 minutes, so 0.1% downtime is about 43 minutes, while 0.3% is about 2 hours and 10 minutes.
- Benefit: an immediate, definite answer. The caller knows whether the work succeeded, so it can show the result or an error right away.
- Benefit: easy to follow. One call produces one reply, and a failure has one obvious place to investigate.
- Cost: shared downtime. When the called service is down, the caller fails too, unless it has a fallback.
- Cost: the sender must know every receiver. If three services must react to a scan, the scanner has to call all three, and a fourth service means changing the scanner.
Events
An event is a record that something has already happened, published so that any interested service can react to it, while the publisher does not wait for any of them. In the words of the Kafka documentation, an event records the fact that "something happened" in the world or in your business. The scan at the van door is an event: parcel P-58210 is out for delivery, and nothing that happens later can make that untrue.
Three services care about this scan. The customer texts service sends the message "Your parcel is out for delivery." The delivery estimates service recalculates the arrival window, and the analytics service counts how many parcels leave each depot per hour. The scanner needs none of their results, so it has no reason to wait for any of them.
In Kafka, a service that publishes events is a producer, and a service that reads them is a consumer. Events are stored in a named stream called a topic, which here is parcel-events. Each event has a key, a value, a timestamp, and optional headers. In this system the key is the parcel ID, and the value describes what happened:
{"type":"ParcelOutForDelivery","parcelId":"P-58210","depot":"North"}
Two properties stated in the Kafka documentation make this arrangement work. First, producers and consumers "are fully decoupled and agnostic of each other," and "producers never need to wait for consumers." Second, events "are not deleted after consumption," so a topic can have many consumers, and each one reads the same events independently.
One Scan, Three Readers
The program below publishes the scan once, and then three services read the topic, each under its own group name. Kafka keeps a separate reading position for each group name, so one service reading the event does not hide it from the others. The full program is about 45 lines; these are the two parts that matter.
try (var producer = new KafkaProducer<String, String>(producerProps)) { // get() waits until Kafka has stored the event, not until anyone reads it. RecordMetadata stored = producer.send(new ProducerRecord<>("parcel-events", "P-58210", event)).get(); System.out.println("stored in partition " + stored.partition() + " at offset " + stored.offset()); }
// Three services read the same topic, each under its own group name. for (String reader : List.of("customer-texts", "delivery-estimates", "analytics")) { // ... consumerProps.put("group.id", reader); consumerProps.put("auto.offset.reset", "earliest"); try (var consumer = new KafkaConsumer<String, String>(consumerProps)) { consumer.subscribe(List.of("parcel-events")); // ... } }
The setting auto.offset.reset=earliest tells a reader that has no saved position to start from the oldest stored event. Each event's position in the topic is its offset, a number that starts at 0. Running the program against a single Kafka 4.4 broker printed the following.
Output:
stored in partition 0 at offset 0 customer-texts read P-58210 from offset 0 delivery-estimates read P-58210 from offset 0 analytics read P-58210 from offset 0
Notice two things in the output. The producer finished as soon as Kafka stored the event, before any reader existed. The analytics service read the event after two other services had already read it, and the event was still there. To keep the output in a fixed order, the program runs the three readers one after another; in production each reader is its own process.
A fourth reader, such as a proof-of-delivery service, would need no change to the scanner. It would subscribe under a new group name and read the same events.
The Deciding Question
Ask one question about every connection: does the sender need the result before it can continue? If it does, the connection is a request. If it does not, and the sender is reporting a fact that others may act on, the connection is an event.
A second question confirms the choice: who decides what happens next? With a request, the sender decides, for example "send this text" or "calculate this route." With an event, the sender only reports what happened, and each reader decides for itself what to do about it. This difference is why requests are usually named as commands, such as SendDeliveryText, and events are named in the past tense, such as ParcelOutForDelivery.
| Connection in the parcel system | Sender needs the result? | Kind | Reason |
|---|---|---|---|
| Tracking page asks for the status of P-58210 | Yes | Request | The page has nothing to show without the answer |
| Driver's handheld saves the scan | Yes | Request | The driver must know the scan was recorded |
| Scan announced to texts, estimates, and analytics | No | Event | The scanner has no use for their results |
| Customer pays a redelivery fee | Yes | Request | The customer must see whether the payment succeeded |
| Paid fee lets the depot schedule a new delivery | No | Event | The payment is complete whether or not the depot has acted |
Requests and Events in One Flow
The second row of the table matters more than it may seem at first. The scan itself starts as a request. The driver's handheld sends the scan to the tracking service and waits for confirmation, because a scan that silently disappears means a customer who never learns that the parcel is coming. Only after the tracking service has saved the new status does it publish ParcelOutForDelivery.
Most event-driven systems follow this pattern: a request records the change, and then an event announces it. The request gives the person who made the change a definite answer. The event lets every other service react without that person waiting for them.
The flow has one weak point. Saving the status and publishing the event are two separate steps, so a crash between them leaves a status that was saved but never announced. Any design that uses this pattern must handle that gap.
What Each Choice Costs
Events are not a newer replacement for requests. Each one is the better choice somewhere, and the table shows where the two differ.
| Request | Event | |
|---|---|---|
| The sender waits for | The receiver's reply | Only Kafka's confirmation that the event is stored |
| If the receiver is down | The sender fails or must retry | The event stays stored (7 days by default), and the receiver reads it when it returns |
| Adding a new receiver | Change the sender | Add a consumer; the sender is unchanged |
| Result available to the sender | Yes, immediately | No |
| Following one action | One call to trace | Several consumers, each acting at its own time |
Events bring four costs of their own:
- Delay. The customer's text goes out only after the texts service reads the event. That may be milliseconds later, or minutes later if the service has fallen behind.
- No answer for the sender. If the texts service cannot send a text, the scanner never finds out, so someone must monitor each consumer separately.
- Repeats. A consumer can receive the same event more than once, for example after a crash, so every consumer must handle a repeated event safely.
- A broker to operate. Kafka itself becomes a system that must stay available.
When a person is waiting for the outcome, use a request. A customer paying the redelivery fee must see "payment accepted" or "card declined." Publishing the payment attempt as an event would leave the customer with no result to look at.
Using This in an Interview
For each arrow in a design, state which kind it is and why: "The tracking page calls the tracking service directly, because the page needs the status to render. The scan is published as an event, because the scanner needs nothing back from the services that react to it."
Two follow-up questions are common:
- "Why not make everything asynchronous?" Some callers need an answer. A customer who pays must see the result, and an event gives its sender no result.
- "What happens if the texts service is down?" The scan event stays stored in the topic. When the service returns, it continues from its saved position, so the customer's text is late but not lost.
Key Takeaways
- A request asks and waits for a reply. An event reports something that already happened, and its publisher does not wait for anyone.
- Decide each connection with one question: does the sender need the result before it can continue?
- Requests give an immediate answer but share downtime: three services at 99.9% each give about 99.7% together.
- Events let any number of readers act on one fact, and a new reader needs no change to the producer.
- In Kafka, reading an event does not delete it, and each reader keeps its own position.
- Most flows combine both kinds: a request records the change, and an event announces it.
The parcel scan shows what events offer: one announcement, several independent readers, and a scanner that never waits. That independence is paid for in delay, monitoring, and repeated deliveries, and the next lesson, What Events Cost, puts numbers on each of those costs.
Practice Questions
Try each question first, then open the answer.
1. A checkout page submits a card payment and must show "paid" or "declined" on the screen. Should the page send a request or publish an event?
<details> <summary>Show answer</summary>A request. The page needs the result before it can continue, because the customer is waiting to see it. An event gives its publisher no result, so the page would have nothing to show.
</details>2. When a user changes a profile photo, the search index, the recommendation service, and the email service each need the new photo. The profile service needs nothing back from them. Which kind of connection fits, and what changes when a fourth service needs the photo?
<details> <summary>Show answer</summary>An event, such as ProfilePhotoChanged. The profile service only reports a fact, and each reader decides what to do with it. A fourth service subscribes to the topic under its own group name, and the profile service does not change at all. With requests, the profile service would need a fourth call added to its code.
3. A page calls four services in a chain, and each service is available 99.95% of the time. What is the availability of the chain, and about how many minutes of failure does that mean in a 30-day month?
<details> <summary>Show answer</summary>About 99.8%, or about 86 minutes a month. The chain works only when all four work: 0.9995 x 0.9995 x 0.9995 x 0.9995 is about 0.998. A 30-day month has 43,200 minutes, and 0.2% of 43,200 is about 86 minutes. One service alone at 99.95% would fail for about 22 minutes.
</details>4. The customer texts service is down for 20 minutes, and 600 parcels are scanned during that time. What happens to those 600 texts if the scanner calls the texts service with requests, and what happens if the scanner publishes events to Kafka?
<details> <summary>Show answer</summary>With requests, the texts are lost unless the scanner retries them. With events, they are sent late. Each request fails while the service is down, so the scanner must either fail the scan or store and retry the call itself. With events, all 600 are stored in the topic. When the texts service returns, it reads from its saved position and sends the 600 texts, each up to about 20 minutes late.
</details>5. An engineer proposes that the tracking page publish a StatusRequested event and then wait for a StatusAnswered event. What is wrong with this design?
It is still a request, now carried over two topics. The page needs the answer before it can show anything, so it waits anyway. It now also has to match each reply to its question and handle a reply that never arrives. The page also depends on Kafka in addition to the tracking service, which adds a failure point without removing any wait.
</details>Reading Progress
0%
On This Page
Requests
Events
One Scan, Three Readers
The Deciding Question
Requests and Events in One Flow
What Each Choice Costs
Using This in an Interview
Key Takeaways
Practice Questions