Imagine a small online store. When a customer confirms a purchase, the application needs to save the order and notify other services. A notification service sends a confirmation, while a shipping service begins preparing the delivery.
This scenario illustrates two distinct responsibilities: storing information and communicating that something happened. Dapr provides APIs for both through its state management and publish/subscribe building blocks.
This article explores a conceptual design rather than a tested implementation.
Saving the Order with State Management
Dapr’s state management API lets applications save and retrieve key/value pairs using a configured state store component. In our store, a key such as order-123 could identify an order’s data.
The application calls the Dapr API, while the component configuration specifies the underlying storage system. This separation can reduce application code changes when switching infrastructure. However, storage systems do not all support the same capabilities or guarantees.
Concurrency matters, too. If two processes update the same order, how should the application handle competing changes? Dapr supports optimistic concurrency control through ETags, but developers still need to select the appropriate behavior and handle conflicts.
A shared API therefore does not remove the need to understand the selected component. Before changing state stores, check their supported features and consistency guarantees.
Read the Dapr state management overview.
Notifying Other Services with Pub/Sub
After saving the order, the application could publish an event to a topic such as orders-created. Interested services subscribe to that topic and process its messages.
Dapr connects to the messaging infrastructure through a pub/sub component. The application uses the Dapr API, while the component configuration supplies the broker-specific connection details.
In our example, the notification and shipping services can each respond to the same event. Each consumer must define what successful processing means and what to do when processing fails.
Dapr pub/sub provides at-least-once delivery semantics, so consumers must account for messages arriving more than once. For a notification service, processing the same event twice could mean sending duplicate purchase confirmations.
One possible approach is to assign each event an identifier and track which events have already been processed. The design must also consider failures between performing an action and recording its completion: simply checking an identifier does not make every operation safe to repeat.
Read the Dapr pub/sub overview.
Connecting State and Events
The proposed flow raises an important question: what happens if saving the order succeeds, but publishing the event fails?
The order would exist, yet other services might never learn about it. Calling two APIs in sequence does not automatically make the operations atomic.
Dapr supports a transactional outbox capability for coordinating state changes and event publication with a compatible transactional state store. Whether it fits a particular application depends on the selected components and configuration.
Even in a small application, this failure case deserves an explicit design decision.
Exploring the Failure Cases
To turn this scenario into a practical learning exercise, I would start with three experiments:
- Deliver the same event twice and check whether the consumer produces duplicate effects.
- Stop a consumer, publish an event, and observe what happens after the consumer restarts.
- Simulate a failure between saving the order and publishing its event, then examine how the application detects and recovers from it.
These are proposed exercises, not test results reported in this article.
Following one order through persistence, publication, and consumption makes each building block’s responsibility easier to understand. It also provides a manageable starting point for learning how a distributed application behaves when part of its workflow fails.
Top comments (0)