Skip to content

CQRS

CQRS (Command Query Responsibility Segregation) is a core architectural pattern in DomusJS, designed to separate commands (write operations) from queries (read operations).

This separation improves:

✅ Scalability.
✅ Maintainability.
✅ System clarity.


CQRS means you split the way your system handles:

  • Commands → actions that change system state (e.g., create user, update profile).
  • Queries → actions that read data (e.g., get user by ID, list videos).

By separating these flows, you can:

  • Optimize read and write models independently.
  • Keep your business logic explicit and modular.
  • Scale reads and writes differently if needed.

DomusJS provides:

  • A CommandBus to dispatch commands to handlers.
  • A QueryBus to execute queries through dedicated handlers.

Example command:

import { Command } from '@domusjs/core';
export class RegisterUserCommand implements Command {
static TYPE = 'REGISTER_USER';
readonly type = RegisterUserCommand.TYPE;
constructor(
public readonly email: string,
public readonly password: string
) {}
}

Example query:

import { Query } from '@domusjs/core';
export class GetUserByIdQuery implements Query {
static TYPE = 'GET_USER_BY_ID';
readonly type = GetUserByIdQuery.TYPE;
constructor(
public readonly userId: string
) {}
}

import { container } from 'tsyringe';
import { CommandBus, QueryBus } from '@domusjs/core';
import { registerCommandHandler, registerQueryHandler } from '@domusjs/infrastructure';
const commandBus = container.resolve<CommandBus>('CommandBus');
const queryBus = container.resolve<QueryBus>('QueryBus');
registerCommandHandler(commandBus, CreateUserCommand, CreateUserHandler);
registerQueryHandler(queryBus, GetUserQuery, GetUserHandler);

Each handler focuses only on its responsibility.

  • Commands: run side effects, change data, emit domain events.
  • Queries: retrieve data, never modify state.

  • Clearer separation between reads and writes.
  • Easier to maintain complex business logic.
  • Better scalability: scale queries separately from commands.
  • Flexibility to evolve read models (e.g., caching, denormalization) without touching write logic.

CQRS adds complexity — you may not need it if:

  • Your system is small and CRUD operations are sufficient.
  • You don’t need different read/write scaling.

But for growing systems, CQRS gives you a solid foundation for clean, scalable design.