The company i'm working for it's rewriting a legacy web application and we are evaluating the better architecture to get the job done.
The business domain is quite simple: there are few entities, few relationships and simple business rules.
We expect a low number of concurrent writes, but a huge number of reads: the expected read workload is much greater than the expected write workload.
The web application is meant to allow a few number of editors to create entities called blogs which are composed by posts. There are different type of posts: textual posts, photos, links to youtube videos, links to twitter posts and so on.
The expected workflow is that an editor, which is following a live sport event, is in charge of editing a dedicated blog which is basically a stream of posts for the event: the editor creates one post for each interesting fact of the event. The main concern is having each post available for the mobile and web clients as soon as possible so that people all around the world will be able to follow the event.
We have evaluated two possible architectures:
- CQRS architecture with two different databases one for the command stack and one for the query stack
- simpler architecture with one domain model supporting both writes and reads and one database
The main advantage of the CQRS approach is the possibility to distribute the content to the clients in an optimized way by using some dedicated read models in order to have simple and fast reads from the read model database. This way the read and write sides can be scaled independently, exploiting the difference between the write and the read workloads highlighted above.
The main advantage of the single domain model approach is a much simpler architecture. In this scenario the commands from the editors are processed synchronously and when a command is successfully processed the editor knows for sure that its work is saved inside the database and available for clients. No eventual consistency between write model and read model, no need to handle the asynchronous update of the read model from the perspective of the backoffice UI users (the editors), no need for any kind of messaging system involved in mission critical tasks.
In my opinion considering our requirements the best way to go is using a single domain model architecture and scaling the reads by using an aggressive caching strategy. The idea is using Redis as a cache in order to limit the database access and trying to update the cache layer each time we write something inside the database using a streaming approach (we will probably use Mongo DB and our first idea is exploiting the change stream feature).
Do you think that a properly sized database and a wise caching strategy with redis could be enough in order to handle our read needs ? Or conversely in a scenario where the read loads is much greater than the write loads the best way to go is using a CQRS architecture (even at the cost of a bigger overall complexity) ?
Some notes to better clarify my question
- I mentioned Redis just as an example of a smart distributed memory cache.The overall idea is having some kind of efficient caching mechanism in order to minimize the database access for readings
- I'm aware that a caching mechanism can be also used when adopting a CQRS architecture (they solve different problems). I highlighted the usage of a cache in the single database architecture because I think that in such a scenario it is mandatory in order to cope with the locking and concurrency over the single database used for both writes and reads
- In this question I intend CQRS as an architectural approach for a whole bounded context (as explained here) and not as a design principle as originally presented by Bertrand Meyer (see here)
- We thought of CQRS as a possible architecture because it is a good choice when you want to independently scale the write and the read sides and you want to have denormalized data ready to be read with a single query (so that reads are fast and efficient). At the same time we have already experienced the complexity that CQRS leads and we are not sure that in this domain it is worth the effort
- The goal of my question is getting some tips and feedbacks (based on real world projects) from more experienced people related to the problem of being able to scale efficiently on the read side of things