I thought I would update this post, since I had to delve into this decision for a new project. I have some data which is inherently normalized (i.e. Student and Course data), and another entity which links to it (i.e. Registration) that has behavior.
So to write a view for Registration:
Denormalize (burden on writer)
++ faster reads, no joins
+ logical failures (e.g. missing data) already handled by writer (faster reads)
- inserts require reading initial data from other tables
- what if data in other tables are not populated?
- extra updates on table when related data changes
Keep normalized (burden on reader)
+ easy insert/update statements
- logical failures must be handled on read (slower reads)
-- joins (slower reads)
Since the purpose of these views are for reading, I decided to denormalize and pay the extra write cost for the fastest reads.
For me, there’s not yet any danger of data from other tables not being populated. But in your scenario, you don’t have perfect ordering due to distributing. Probably, I would just default to “Loading…” for unpopulated strings.
The other thing I learned in this exercise is that denormalized views require patch updates to multiple rows. E.g. StudentUpdated -> “UPDATE Registration SET StudentName = @StudentName WHERE StudentId = @StudentId”
My initial strategy (with very “normalized” mindset) was to keep a Registration (or any other view) object in memory, batch updates to it (during replay), and sync to DB periodically or when the subscription hit live. But with denormalized views, there’s no way to know that I have all affected objects in memory without asking the DB. So no real time savings.
Patch updates are batchable in some DBs… e.g. in SQL, keep the statement and its parameters in memory until a certain threshold, then run them all as one statement.
Another alternative is to setup a projection in EventStore, either to fold to current state of the denormalized view or to filter events down to only the ones needed for your denormalized view. I might explore this option further. It is difficult for me to pick this option, because there is more flexibility (but more initial work) in building the views myself.