AuraFlow: What Happens Between Saving a Product and Sending Its Event?
Follow a product update through AuraFlow to understand event-driven services, the gap between two writes, and what retries and sagas need to get right.
The product saved. Did everyone hear about it?
Imagine adding a product to a supply-chain application. The inventory service stores it successfully, then tries to announce the change. That second operation fails. The product exists, but downstream services may never learn about it.
This is the most useful place to enter AuraFlow. The project combines Spring Boot services, DynamoDB storage, SQS messages, and notification helpers. Its broader design explores event-driven supply-chain workflows. The concrete implementation gives us a small sequence we can inspect: save a product, publish an event, return a response.
We'll follow that sequence first, then use its failure window to understand why reliable event-driven systems need more than a queue. The saga discussion is a design extension; the published saga helper currently simulates starting and compensating a transaction.
One product, four steps
From product request to response
Choose a step to see what happens and why it matters.
A product request reaches the controller, where request-body validation runs before creation. Invalid input can be rejected before it changes storage.
Here is the implemented controller path. Indigo receives and responds, slate holds inventory, and amber carries the event. The order of the arrows matters: storing the product and publishing its event are separate calls.
The source makes that sequence unusually easy to see. These are the three central lines from the creation endpoint, with validation and surrounding method code omitted:
productRepository.save(product);
eventPublisher.publishEvent("PRODUCT_CREATED", product.getId());
return ResponseEntity.status(HttpStatus.CREATED).body(product);
That is a dual write: one logical operation changes two systems. Seeing both calls in the same method doesn't make them one atomic transaction.
Why publish an event at all?
A direct call says, “Do this now.” An event says, “This happened.” Once a product has changed, another part of the application might need to update a report, send a notification, or prepare related work.
An event lets the inventory service describe the change without embedding every downstream action in the HTTP request. In AuraFlow, the publisher constructs a small JSON message containing eventType and productId, then sends it to SQS. The repository also contains shipment publishing and SNS notification helpers.
There is a useful limit to this description: those helpers and infrastructure definitions are building blocks. They do not by themselves establish a fully connected workflow with durable recovery. The inspected worker consumer prints a message, and its processor simulates whether input is nonempty.
A direct call makes completion easy to follow but couples the request to the next service's availability. A queue creates a handoff and a place to wait, while introducing message state, duplicate handling, and delayed outcomes that the application must explain.
The gap a queue cannot close
Return to the failure after the product save. The controller has no single transaction spanning DynamoDB and SQS. If publication fails, the database change may already exist even though the client does not receive the expected success response.
Pause and predict: should the client simply repeat the request?
Repeating might create another change or publish another event, depending on the identifiers and write behavior. Before treating a retry as safe, define the intended final state. A stable operation identifier and idempotent effects help distinguish a repeated delivery from a genuinely new operation.
One possible extension is a transactional outbox: commit a change and a record of the event to send within the same local transaction, then have a separate publisher deliver pending records. That design moves the failure problem into a durable, inspectable publication process. It is a proposed extension here, not a claim about AuraFlow's current controller.
Even then, the publisher can send an event and fail before marking it sent. Consumers still need to handle duplicates. Reliability comes from the entire chain of decisions, not one architectural label.
A retry and a compensation answer different questions
A retry asks, “Can we attempt this action again?” A compensation asks, “How do we address an earlier action that already succeeded?”
For an illustrative supply-chain order, reserving stock might succeed before shipment creation fails. Retrying shipment creation may be appropriate for a temporary problem. Releasing the reservation may be appropriate if the order cannot proceed. That release is another business action; it isn't time travel that erases every effect of the reservation.
This is the idea behind a saga: local steps, recorded progress, and deliberate compensating actions. AuraFlow's SagaManager exposes start and compensate methods, but their inspected bodies log messages and return success. A durable saga would additionally need persistent progress, defined recovery policies, and handling for compensation failures.
| Failure | First question to answer |
|---|---|
| Event publication fails after a save | Where is the intent to publish recorded? |
| A message arrives twice | Which identifier makes the effect safe to repeat? |
| A later business step fails | Should it retry or trigger compensation? |
| Compensation also fails | Who records and resumes recovery? |
What the performance number actually describes
The repository README reports roughly 40,000 events per minute from a local DynamoDB benchmark: 10,000 events in about 15 seconds. It explicitly describes this as local event-sourcing throughput.
That is a narrower claim than an end-to-end AWS deployment sustaining the same rate through inventory changes, SQS, worker processing, and notifications. It doesn't establish an uptime or delivery guarantee. A useful benchmark story names the stage measured before presenting the number.
The same care applies to the autoscaling and error-handling helpers: the inspected versions simulate behavior with log messages. They're places to develop operational policies, not evidence that those policies have already run under production load.
What I would test next
Force publication to fail after a successful product save. Deliver the same event twice. Stop a consumer after its side effect but before completion is recorded. Then ask whether the application can tell the difference between work that never happened, work that happened once, and work whose outcome is uncertain.
Those are proposed validation cases. They help turn a collection of services into a workflow with promises a user can understand.
The takeaway from AuraFlow is the boundary between an action, the event describing it, and the work that follows. Once those are explicit, choices about queues, retries, and sagas become much less mysterious.
Explore the implementation
Source reviewed at revision f0aabb1:
Related Posts
K2-Consensus: What Does an AI Panel's Agreement Actually Mean?
Explore a proposed expert-panel workflow through three critiques and a moderator. Learn how useful disagreement differs from voting, evidence, and distributed consensus.
Aegis: From a Security Finding to an Explanation You Can Check
Follow one scan through Aegis to see how network checks become findings, where Gemini helps, and why a readable report still needs traceable evidence.
MedInsight: Following a Request from Go to Gemma 2
Why split a medical analysis workflow between Go and Python? Follow one request through MedInsight to understand the queue, the model worker, and the tradeoffs behind the architecture.