I can see Temporal being great for the Write Side (Domain Model) but I can’t understand how the Read Side (View Models) may work.
I guess a Temporal workflow for an aggregate could use an activity to add an event to an external event stream that was used by one or more other workflows to build or rebuild one or more read-side view models.
I would use Temporal for write side and another system for reads. IMO Apollo Federation is the best system for distributed reads. The read system may source some data from Temporal through Temporal Queries—e.g. when that piece data lives in the state of running Workflows—and the rest from OLTP DBs or read DBs. Temporal may be writing data to those DBs—for example, at the end of a Cart Workflow, after a successful checkout, the last activity may create a record in the Orders DB. If you want a denormalized read DB, for example OrdersWithUserAndItems, to then be updated, there are a few ways:
- The Cart Workflow could have another activity at the end that does the update.
- You could use a CDC-based system like Debezium to get OrdersWithUserAndItems updated after the Temporal activity inserts into the Orders DB.
- The method you mentioned: an activity at the end of the Workflow emits an OrderCreated event to Kafka, and a consumer does the DB update.
For rebuilding OrdersWithUserAndItems from scratch, replaying the event logs of #2 and #3 are straightforward. For #1, the event log is there (an ActivityTaskScheduled event in the Cart Workflow history with timestamp and input arguments), but replaying it is not straightforward—you can’t just tell Temporal “rerun all update-OrdersWithUserAndItems activities in the order they were executed”. You can only run new Workflows. So anything you want to be re-runnable should be a Workflow. So if you wanted to do the update logic inside Temporal, instead of #1, I’d do a modified version of #3:
3b. At the end of the Workflow, start an OrderCreated Workflow (starting a Workflow is effectively emitting an event) that does everything the OrderCreated consumers did in #3, including updating OrdersWithUserAndItems.
Then rebuilding OrdersWithUserAndItems would be replaying the OrderCreated Workflows in the same order with the same arguments. I haven’t tried this, and I’d be inclined toward your #3 over 3b.
More generally re: how having an event-sourcing-based system fits with Temporal, while Temporal internally uses event sourcing, there are some differences and limitations of using Temporal’s internal log compared to using Kafka history. And usually not all writes go through Temporal—in that case, in order to have event sourcing that covers all events/actions, it needs to be done outside Temporal; for instance, all events go to Kafka, and some consumers start Workflows.