- β CQRS (Command Query Responsibility Segregation) pattern implementation for modern e-commerce systems.
Used Technologies in The Project:
CQRS = Separate Write and Read operations!
Traditional Approach:
User β API β Single Database (PostgreSQL)
β
Write & Read (Slow!)
CQRS Approach:
User β API β Command (Write) β PostgreSQL
β Query (Read) β Elasticsearch (Fast!)
Real World Scenario:
In an e-commerce site:
- π Product purchase: 10% (LOW)
- π Product viewing: 90% (HIGH)
Problem:
- You're both writing and reading from PostgreSQL
- Millions of users searching products simultaneously β SLOWNESS!
Solution: CQRS
- Write (Command) β PostgreSQL (Strong, ACID)
- Read (Query) β Elasticsearch (Fast, Search)
User β "Add new product"
β Command API
β Save to PostgreSQL
β Send event to RabbitMQ
Endpoint:
POST /api/commands/products
Content-Type: application/json
{
"name": "iPhone 15 Pro",
"price": 45000.0
}User β "Search iPhone"
β Query API
β Fetch from Elasticsearch (β‘ Fast!)
Endpoint:
GET /api/products?name=iPhone-
Admin adds new product
- Written to PostgreSQL
-
RabbitMQ publishes event
- ProductCreatedEvent
-
Listener catches event
- Written to Elasticsearch
-
Users search quickly
- Read from Elasticsearch
| Technology | Purpose | Why? |
|---|---|---|
| PostgreSQL | Write Database | ACID, reliable writes |
| Elasticsearch | Read Database | Fast search, full-text search |
| RabbitMQ | Event Bus | Asynchronous communication |
| Spring Boot | Framework | Rapid development |
docker-compose up -d- PostgreSQL
- URL:
http://localhost:5432 - Database:
cqrs_example - Username:
postgres - Password:
postgres
- URL:
- Elasticsearch
- URL:
http://localhost:9200 - Username:
elastic - Password:
elasticsearch
- URL:
- RabbitMQ Management
- URL:
http://localhost:15672 - Username:
rabbitmq - Password:
rabbitmq
- URL:
./gradlew bootRunCreate product:
curl -X POST http://localhost:8080/api/commands/products \
-H "Content-Type: application/json" \
-d '{"name":"Laptop","price":15000.0}'List products:
curl http://localhost:8080/api/productssrc/main/java/com/furkankayam/
βββ command/ # π WRITE side
β βββ Product.java # JPA Entity
β βββ ProductCommandRepository.java
β βββ ProductCommandService.java
β βββ ProductCommandController.java
β
βββ query/ # π READ side
β βββ ProductDocument.java # Elasticsearch Document
β βββ ProductQueryRepository.java
β βββ ProductQueryService.java
β βββ ProductQueryController.java
β
βββ event/ # π Events
β βββ ProductEvent.java
β βββ ProductEventPublisher.java
β βββ ProductEventListener.java
β
βββ dto/ # π¦ Data Transfer Objects
β βββ request/
β β βββ CreateProductRequest.java
β β βββ UpdateProductRequest.java
β βββ response/
β βββ ProductResponse.java
β
βββ config/ # βοΈ Configuration
βββ RabbitMQConfig.java
POST /api/commands/products # Create product
PUT /api/commands/products/{id} # Update product
DELETE /api/commands/products/{id} # Delete productGET /api/products # All products
GET /api/products/{id} # Product by ID
GET /api/products/search?name=... # Search by name
GET /api/products/search/price?min=...&max=... # Search by price1000 users searching "iPhone" simultaneously
ββ> PostgreSQL JOIN queries
ββ> Slow! (500ms - 2s)
ββ> Database locked!
1000 users searching "iPhone" simultaneously
ββ> Elasticsearch full-text search
ββ> Fast! (10ms - 50ms)
ββ> PostgreSQL unaffected!
| Operation | Traditional | CQRS |
|---|---|---|
| Create product | 50ms | 50ms |
| Search product | 800ms | 20ms |
| 1000 users searching | DB locked | Working smoothly |
- Unbalanced read/write ratio (90% reads, 10% writes)
- High traffic
- Complex search requirements
- E-commerce, blogs, news sites
- Simple CRUD applications
- Low traffic
- Balanced read/write operations
This project is licensed under the MIT License. See the LICENSE file for details
Created by Mehmet Furkan KAYA
