Part 05 of 16 · Day 1 · aggregate, optimistic concurrency
Concurrent changes to one application
Problem and experience
Who changed the application, and are they allowed to?
The rule “instalment at most 45% of income” must hold even when two advisers change the application at once.
- Adviser Aloaded v5
- Adviser Bloaded v5
- Applicationboth write
- Rule violatedinstalment limit
From practiceHow do you find out today who changed a key value of an application, and when?
TakeawayApplication rules need one place and a clear version on which decisions are made.
What it means
The Application module holds the application rules (limits, required fields) and decides on changes.
Why we use it
Rules in one place are easy to test and individual screens can't bypass them.
When it makes sense
Whenever rules depend on the current state of the application.
Where it breaks
- A rule enforced only in the form.
- A decision based on stale state.
- No trail of the change.
Imagine
Adviser B finishes the calculation on the old price. Without a version check, a closed calculation is created that exceeds the instalment limit.
A rule is only as strong as the reliability of the one place that enforces it.
Principle, application and exercise
Application stores state in a table, or as events
The Application module holds the application rules. How it stores state is a choice. EDA does not require Event Sourcing.
Option A: table with a version
- Command
- Applicationrules + version
- RowexpectedVersion
- Eventafter write
Option B: Event Sourcing
- Command
- Applicationpravidla
- Event streamappend-only
- Statusfold(events)
Trade-offEvent Sourcing gives full history and replay, but costs event versioning, projections and team habits. For many modules a table with a version is enough.
TakeawayEvent Sourcing is a choice of the Application module, not a prerequisite for EDA.
What it means
Event Sourcing stores a sequence of events and builds state from them. The alternative is a table with a version number, where a write against a stale version fails (optimistic concurrency).
Why we use it
History, audit and the ability to derive a new view are only useful where we really need them.
When it makes sense
Event Sourcing where it matters what happened and why (finance, disputes, audit). A versioned table where the latest state is enough.
Where it breaks
- Event Sourcing everywhere “just in case”.
- Events carrying computed values for the UI instead of facts.
- Simply retrying the write after a conflict without a new decision.
Imagine
Six calculation events: CalculationCreated, IncomeChanged, PropertyPriceChanged, RateChanged, TermChanged, CalculationCompleted. The aggregate enforces the instalment limit rule.
The system only remembers what we decided to record, and it does not have to remember it everywhere.
Training for your team
Would you like this training for your team?
We run the training on your code and your domain problem. We agree the scope, dates and format with you.
Discuss the training →