System design - noordwind/Collectively.Api GitHub Wiki

The design of Collectively system is heavily based on the microservices and CQRS patterns. What does it mean in practice? Let's see:

  • Each service is an independent project (as well as the repository), therefore it can be developed and deployed with its own lifecycle without interfering the other parts of the system.
  • Services have their own databases that are suited for their needs. It also eliminates the bottlenecks related to the data reads or writes.
  • Services focus on a single domain and responsibilities that are related to the entities. For example handling the user authentication is a totally different task than filtering the remarks.
  • Services can easily scale independently from each other. All you need to do is to spawn a new instance of the particular service - the horizontal scaling has a much bigger advantage over the vertical one.
  • Services have no idea about the other parts of the system - they're just "unit of work" that processes the commands and publishes events. Loose coupling is the key while designing microservices.
  • Services share their commands, events, DTOs and operation codes in a form of NuGet package that name ends with .Shared, so it can be referenced by other projects.
  • CQRS allows separating reads from writes, which eventually turns into much easier scaling as you can easily distinguish between the commands and the queries.
  • Data is being held in a very efficient, read-only storage that contains already "flattened" objects ready to be returned to the end users directly.

The picture below represents the design of the Collectively system:

Having the general overview of the Collectively architecture, let's describe its core parts:

  • API - acts as a gateway to the whole system, that receives the user requests (translated into commands and queries) via HTTP requests. It is aware only of the service bus for publishing the commands and the storage service which is being used for retrieving the data via queries.
  • Storage - handles storing the data using its internal database. It does subscribe to the particular events in order to fetch the data from a particular service and "flatten" the object accordingly so it's directly ready to use by the end user. The data storage client which is the API in our system is not being aware where does the data come from (storage database, cache, some other service etc.) which makes this service a truly transparent data provider.
  • Microservices - a set of services that are independent of each other (and also unaware of anything else besides their own tasks that are related to handling the particular commands and events), which are being tied to the specific domain and business logic. However, service A can ask service B in order to fetch the specific resource if it needs it via simple HTTP GET request.