Temporal and CQRS

Hi,

Very interesting new technology, thanks for all your work and for sharing.

Can someone please explain if/how Temporal could be used to implement CQRS (with Event Sourcing) or, with a gulp, does this replace CQRS?

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.

In essence, keen to hear thoughts on CQRS/ES and Temporal.

Thanks,
Ashley.

1 Like

I’m not an expert on CQRS, so correct me if I misrepresent it.

Temporal is not a technology to implement CQRS. It is a technology that can be used instead of it for a large number of use cases.

My understanding that the main reason for using CQRS is a desire to build an event based architecture. But it comes with many drawbacks. Mostly around eventual consistency and being a pretty low-level abstraction for developers to deal with directly. CQRS by itself is just a pattern. It still requires choosing particular implementations of event storage, durable timers, and associated client-side libraries.

Temporal is fully event-based and asynchronous. It is an architectural style, programming model, and concrete production-ready implementation. Temporal abstracts out most of the complexity of building and operating resilient processes from short to never-ending ones. Internally Temporal uses event sourcing for recovering program state, but it is more like implementation detail that does not affect directly how applications are designed and written.

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.

In Temporal a unit of computation is called Workflow. The workflow can contain a very complex domain model. Workflow has its own threads to drive activity executions and it can react to asynchronous external events. It supports read operations to its state directly through a sychronous query feature. Temporal workflow is fully consistent. So it doesn’t have a problem that CQRS has with eventual consistency of view models.

Temporal allows creating service oriented architectures that consist of workflows and activities that are hosted by different services and invoke each other. You can think of Temporal as a service mesh that supports operations of unlimited duration.

1 Like

Thank you for your reply Maxim.

There are many variations of CQRS but I would say most enterprise implementations use a distributed architecture and thus face all of the issues that Temporal addresses. The most common variations also use event-sourcing to build and rebuild domain aggregates (entities) when needed to apply commands on them, which Temporal also does (amongst other things).

However, these variations also use the event-stream to build and rebuild the current and potentially new (and often denormalised) read-sides (view models) as / when needed. 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.

A Temporal version of CQRS wouldn’t need to worry about rebuilding the aggregates. However, it seems somewhat redundant to recreate an external event stream that’s similar to one already created by Temporal and used to rebuild the state (and other part of the apps). Of course, I am not sure what form the event-sourcing in Temporal takes and it builds much more than just the domain state.

One of the advantages of the popular approach to CQRS with Event-Sourcing is also that the write-side and read-side are able to scale independently. As we know, many applications have a much higher load on the read-side (queries) that the write-side (commands to change the aggregates). Can Temporal scale it’s handling of queries (read-only) for different aggregates (entities)?

The query feature is pretty cheap in Temporal as it doesn’t involve persistence writes or even reads if a workflow is already cached on a worker. So I would say that Temporal indeed scales better for reads than writes. If you want to sacrify consistency for performance we can always add a cache for query results to optimize it even more.