Laravel CQRS: Khi nào nên dùng và nó giải quyết vấn đề gì?
CQRS tách đọc và ghi thành hai luồng riêng. Không dùng thì code dễ rối và đọc/ghi tranh tài nguyên. Dùng vào giúp tối ưu hiệu năng, rõ logic và dễ scale. Phù hợp khi hệ thống lớn, query nặng, traffic đọc cao.
Trước khi áp dụng CQRS, hệ thống Laravel của bạn thường dùng chung một quy trình và một bộ model cho cả đọc và ghi. Điều này đơn giản nhưng dễ gây tắc nghẽn khi hệ thống lớn dần: query đọc phức tạp ảnh hưởng hiệu năng ghi, code controller phình to, và việc bảo trì trở nên khó khăn.
CQRS giúp tách biệt luồng đọc và ghi thành hai khối độc lập – Query và Command – giúp tối ưu hiệu năng, mở rộng hệ thống dễ hơn, và duy trì business logic rõ ràng. Bạn chỉ nên áp dụng CQRS khi hệ thống bắt đầu tăng trưởng, có yêu cầu đọc lớn, hoặc cần tính mở rộng cao.
1. Trước khi dùng CQRS thì Laravel vận hành ra sao?
Mặc định, Laravel dùng kiến trúc CRUD (Create – Read – Update – Delete) với một layer xử lý cho cả đọc và ghi.
Nghĩa là:
Một Controller/Service vừa xử lý read (GET data)
Vừa xử lý write (tạo/sửa/xóa)
Model/Eloquent cũng là thứ bạn dùng chung cho cả đọc và ghi.
PHP
class UserController {
public function index() {
return User::where('is_active', 1)->paginate(10);
}
public function update(Request $request, User $user) {
$user->update($request->all());
return $user;
}
}Tất cả chung một model → chung một DB schema → chung một flow.
Điều này đơn giản, dễ code, phù hợp 90% dự án nhỏ.
Nhưng có vấn đề khi hệ thống lớn dần, ví dụ:
Vấn đề khi không dùng CQRS
Read & Write “đánh nhau”
Query đọc cần nhiều join, filter, sorting → làm API chậm
Query ghi thì cần đảm bảo tính nhất quán
→ Cùng chạy chung một DB → dễ nghẽn.
Code controller/service càng ngày càng phình to
Một endpoint có thể vừa validate, vừa query phức tạp, vừa mutate DB.Khó scale
Bạn muốn scale read (cache, replica) và write (transaction, consistency) khác nhau → kiến trúc CRUD cũ không hỗ trợ.Không theo dõi được logic business rõ ràng
Logic đọc bị trộn với logic ghi
Tính audit, logging, event tracking rất khó thêm.
2. Sau khi áp dụng CQRS thì giải quyết vấn đề gì?
CQRS = Command–Query Responsibility Segregation.
Bạn tách hệ thống thành 2 phần:
Query: chuyên để đọc
Tối ưu riêng cho tốc độ, lọc, sắp xếp
Có thể dùng ViewModel, DTO, Eloquent nhẹ
Có thể dùng Redis, Elasticsearch, DB replica để tăng tốc
Command: chuyên để ghi
Tách domain logic rõ ràng
Chạy theo pattern Command Bus/Action
Dễ thêm queue, event sourcing, transaction
PHP
/app/Domain/Users/Commands/UpdateUser.php
/app/Domain/Users/Queries/GetActiveUsers.phpKhi áp dụng:
Bạn giải quyết được:
1) Scale read/write độc lập
Read scale: cache, DB replica
Write scale: queue, event sourcing
Không còn block nhau.
2) Tách rõ logic business
Command = hành động thay đổi state (update/delete)
Query = lấy dữ liệu hiển thị
→ Code dễ đọc hơn, dễ test hơn.
3) Dễ thêm các hành vi: logging, event, auditing
Command là nơi lý tưởng để bắn event:
PHP
class UpdateUserHandler {
public function handle(UpdateUser $command) {
// update user
event(new UserUpdated($user));
}
}4) Giảm phình controller
Controller chỉ nhận request → gọi Query/Command → trả response.
3. Khi nào nên áp dụng CQRS trong Laravel?
Không phải dự án nào cũng cần CQRS.
Dưới đây là guideline chuẩn để quyết định.
Nên dùng CQRS khi:
Hệ thống có lượng đọc nhiều hơn viết
(dashboard, social feed, analytics)Query đọc phức tạp → nhiều join → dễ nghẽn
Business logic ghi phức tạp (nhiều bước, nhiều rule)
Bạn muốn dùng:
Event-driven
Queue
Domain-driven design
Microservices
Khi team cần code dễ bảo trì, chia module rõ ràng
Không cần dùng CQRS khi:
Startup mới làm MVP
Blog nhỏ, CRUD đơn giản
Dự án cá nhân, nhỏ, ít traffic
Không có yêu cầu scale nhanh