ken
ken

Reputation: 2672

How to build Microservices with CQRS pattern using Nestjs?

Recently come across to Microservice architecture and CQRS (command query responsibility segregation), I can understand both concept, but I am confuse when 2 pattern come together, how can we implements this 2 pattern all together?

First of all, based on my understanding, in Layman terms,

Microservice is like break the different part in our app into different 'small app'. For example, our app have Product, Order, Payment, Invoice etc, each of this function can be break it down to separate Nestjs microservices app and host it into different docker container or different server may be? Which stated here https://docs.nestjs.com/microservices/basics we can defined the app like this:

import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { ProductModule } from './product.module';

async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    ProductModule,
    {
      transport: Transport.TCP,
    },
  );
  app.listen();
}
bootstrap();

Then inside this app, it only handle 1 operation, example Product.

Therefore after we have this Product microservice, I can have a Nestjs app named gateway which will redirect the traffic to Product service using MessagePattern, same goes to Order, Invoice, Payment etc. Between Order and Payment, then can communicate using EventPattern Which is basically look like this:

enter image description here

Question 1: So with the structure above, is it each of the service have to host in 5 server? Cause when all of them, lets say 5 docker container host in 1 server, how will this useful? Cause I didnt see the value of this so far.

Next, is about CQRS, which stated documentation here

I tried to implement this, then I will get the file structure like this:

enter image description here

Is basically inside 1 Nestjs app which do this following:

Question 2: But right now, since all that is still inside 1 Nestjs app, so is this consider a Monolith application? Or let say account folder already consider 1 Microservices? I need to be clear for this first.

If the structure in the picture above, is a monolith, I am thinking to break it down to Microservice using Nestjs monorepo mode,

apps
- productService # --> this is 1 microservices
-- src
--- main.ts // as stated here
--- product.controller.ts
--- product.module.ts
--- product.service.ts
- orderService   # --> this is 1 microservices
- paymentService # --> this is 1 microservices
libs
- productLibs
-- domain // basically this is the 2nd picture
-- infrastructure 
-- application 
- orderLibs
- paymentLibs

So when deploy, I will build the docker image like this:

Ok, by doing this, I can use the command, query, event of each domainLibs in all different domainService. But right now have a problem:

Question 3: How can I trigger orderService from productService? Let say in the command handler like below:

// Inside Product service in libs
@CommandHandler(ProductItemCommand)
export class ProductItemHandler
  implements ICommandHandler<DropAncientItemCommand> {
  constructor(
    private readonly repository: HeroRepository,
    private readonly publisher: EventPublisher,
  ) {}

  async execute(command: DropAncientItemCommand) {
    // here how to trigger OrderService? 
    // with EventPattern or MessagePattern? 
    // But this is inside `libs` folder
  }
}

Question 5: Do we need to use Microservices when we already implement CQRS in an app? If yes, how each microservice share command, query, event with each other? Let say ProductDomain at some point need a command from OrderDomain?

Question 6: Can use CQRS and Microservice together? If yes, what is the benefit on this? In what use cases?

Question 7: What is the different and relationship between Microservice and CQRS? So it is a Microservices vs CQRS relationship or Microservice + CQRS relationship?

Just document all my thinking based on my research. Please point me to a right direction, like industry standard AKA how you all normally do things.

Upvotes: 3

Views: 1848

Answers (1)

Marko Eskola
Marko Eskola

Reputation: 818

Answer 1:

In a scalable cloud application every service is run behind load balancer in auto scaling groups. When there is low traffic only a few instances of a service are run, when the traffic increases new tasks will be started. Load balancer routes traffic to different container instances.

Services can be run in one server or several servers or in the cloud in clusters. There are a lot of different archictural approaches ( see for example different cloud providers' container services). However, selecting mciroservcices architecture usually means that the application is scalable and one service will be run as multiple instances. From financial viewpoint this is useful and makes sense: resources are used when needed and compute costs vary accordingly.

Answer 2:

That seems to be a correct approach to divide apps into several containers.

Answer 3:

You transfer data betweeen different services like between front end application and backend, for example using, REST, HTTP, Websocets API. In layman's terms, you need to establish network connection between different services.

Question 4 was missing.

I am not familiar with CQRS so the answers below are less or more opions than fact.

Answer 5:

No.

Answer 6:

Microservices and CQRS are not competing concepts. You can use CQRS in a monolitic app or as a part of microservices architecture.

Answer 7:

Its microservices + CQRS. You can implement microservices architecture without CQRS.

Upvotes: 2

Related Questions