Mastering CQRS: How to Split Commands and Queries for Scalable Java Backends

This article explains the CQRS pattern, contrasts it with traditional CRUD, outlines its architectural benefits, presents two implementation approaches—including shared and separate databases—and provides a step‑by‑step Java example with command interfaces, a CommandBus, and controller integration, helping developers adopt CQRS in real projects.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Mastering CQRS: How to Split Commands and Queries for Scalable Java Backends

Today we share what CQRS (Command Query Responsibility Segregation) is and how to use it in a project.

1. CRUD System

In the familiar three‑layer architecture, the data access layer handles both modifications and queries using the same entity. Business logic is processed in the service layer, results are wrapped in DTOs, and the controller renders them to the front end.

This design works for simple projects, but as business logic grows and user volume increases, performance issues arise. A common remedy is read‑write separation at the database level, with a primary database handling transactional writes and replicas handling reads. However, the read and write logic remain coupled to the same entity.

At this point CQRS becomes relevant.

2. CQRS System

Simply put, CQRS splits a CRUD system into two parts: Command handling (create, update, delete) and Query handling (read). Commands modify data, while queries retrieve it, allowing each side to be optimized independently.

3. CQRS Implementation Methods

There are two main ways to implement CQRS:

1) Both sides share the same database but separate code. This keeps data consistency simple while allowing logical separation.

2) Both sides have separate databases; the query side synchronizes data from the command side. Synchronization can be synchronous (strong consistency) or asynchronous (eventual consistency). The command side may use Event Sourcing, storing state changes as domain events, while the query side reads from a dedicated read database.

4. Simple CQRS Implementation

Below is a minimal Java example using the first approach (code separation, shared database).

First, define a generic command interface:

public interface Command<T> {
    Object execute(T commandModel);
}

Then create a concrete command for adding an order:

@Component
public class CreateOrderCommand implements Command<CreateOrderModel> {
    @Override
    public Object execute(CreateOrderModel model) {
        // specific logic
    }
}

A CommandBus dispatches commands to their handlers:

@Component
public class CommandBus {
    public Object dispatch(Command cmd, Object model) {
        return cmd.execute(model);
    }
}

Finally, the controller invokes the bus:

@RestController
@RequestMapping("/order")
public class OrderController {
    @Resource
    private GetOrderInfoService getOrderInfoService;
    @Resource
    private CreateOrderCommand createOrderCommand;
    @Resource
    private CommandBus commandBus;

    @PostMapping("/getInfo")
    public Object getOrderInfo(GetOrderInfoModel model) {
        return getOrderInfoService.getOrderInfos(model);
    }

    @PostMapping("/create")
    public Object createOrderInfo(CreateOrderModel model) {
        return commandBus.dispatch(createOrderCommand, model);
    }
}

This demonstrates how commands are routed through the bus, while queries go directly to the service layer, embodying the CQRS principle.

5. Summary

CQRS is a clear design pattern that separates operations and queries, improving scalability and performance and allowing independent optimization of each side. All database interactions are performed via commands, which can be synchronous or asynchronous depending on business needs. While conceptually simple, CQRS introduces additional complexity and often overlaps with Domain‑Driven Design concepts.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaCQRSCommand Bus
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.