A scalable, cloud-native e-commerce backend built with Java 21 and Quarkus, featuring a microservices architecture managed by Consul for service discovery and Kafka for event-driven communication.
The system is composed of loose-coupled microservices that communicate synchronously via REST APIs and asynchronously via Kafka messaging.
| Service | Technology | Port | Description |
|---|---|---|---|
| Authentication Service | Quarkus, PostgreSQL, Redis | 8080 |
Manages identity, JWT issuance (ECC), registration, and RBAC. |
| Order Service | Quarkus, PostgreSQL, Outbox | 8081 |
Manages order lifecycle with transactional outbox pattern for reliable event publishing. |
| Product Service | Quarkus, MongoDB, Redis | 8082 |
Manages product catalog, stock levels, and category listings. |
| Notification Service | Quarkus, Kafka | 8083 |
Consumes events from Kafka to send emails (Discord, Brevo). |
| Kafka Connect | Debezium | 8084 |
CDC connector for capturing changes from outbox table and publishing to Kafka. |
| Component | Port | Purpose |
|---|---|---|
| PostgreSQL | 5432 |
Order and Auth databases (with logical replication for CDC) |
| PostgreSQL Auth | 5433 |
Authentication service database |
| MongoDB | 27017 |
Product catalog database |
| Redis | 6379 |
Caching layer |
| Kafka | 9092 (internal), 9093 (external) |
Event streaming platform |
| Zookeeper | 2181 |
Kafka coordination |
| Kafka Connect | 8084 |
Debezium CDC connector |
| Prometheus | 9090 |
Metrics collection |
| Grafana | 3000 |
Monitoring dashboards |
| Jaeger | 16686 |
Distributed tracing |
- Order Service uses Debezium CDC for guaranteed event delivery
- Events are persisted in the
outboxtable within the same transaction as business data - Kafka Connect captures changes and publishes to Kafka topics
- No event loss even if Kafka is temporarily unavailable
- Order.events - Unified topic for all Order events (OrderCreated, OrderStatusChanged)
- product-created / product-updated / product-deleted - Product lifecycle events
- stock-changed - Inventory updates
- authentication-email - User registration and password recovery events
- Dead Letter Queue (DLQ): Failed events are sent to
outbox.event.Order.dlqafter 3 retry attempts - Exponential Backoff Retry: Progressive delays (2s β 4s β 8s) for transient failures
- Enhanced Observability: DEBUG-level logs for
com.ecommerce.*in development, INFO in production - Native Image Reflection: All DTOs properly configured for GraalVM native compilation
- Zero Data Loss: Events preserved in DLQ for manual investigation and reprocessing
- Java 21+ (JDK)
- Maven 3.8+
- Docker & Docker Compose
- OpenSSL (for generating JWT security keys)
-
Clone the repository:
git clone <repository-url> cd ecommerce-microservices
-
Generate Security Keys (Required for Auth):
cd authentication-service # Generate ECC keys as described in authentication-service/README.md cd ..
-
Start all services:
docker-compose up -d
-
Verify services:
# Check service health curl http://localhost:8081/q/health # Order Service curl http://localhost:8082/q/health # Product Service curl http://localhost:8083/q/health # Notification Service # Check Kafka Connect curl http://localhost:8084/ # Check Debezium connector status curl http://localhost:8084/connectors/order-service-outbox-connector/status
# Run the automated integration test
cd order-service
./scripts/test-outbox-integration.shFor detailed setup and testing instructions, see:
- OUTBOX-QUICK-START.md - Quick start guide
- order-service/KAFKA-CONNECT-SETUP.md - Complete setup guide
# Start all services (infrastructure + applications)
docker-compose up -d
# View logs
docker-compose logs -f
# View specific service logs
docker-compose logs -f order-service
docker-compose logs -f kafka-connect
# Stop all services
docker-compose down
# Stop and remove all data volumes (clean state)
docker-compose down -vBuilding multiple Quarkus services in native mode simultaneously is resource-intensive. Use the sequential startup script:
# Build and start everything sequentially
./sequential-up.sh --build
# Just start containers sequentially
./sequential-up.sh upThis script starts infrastructure first, waits for stabilization, then builds/starts each app one by one.
# Check running containers
docker-compose ps
# Check Kafka Connect health
curl http://localhost:8084/
# Check Debezium connector status
curl http://localhost:8084/connectors/order-service-outbox-connector/status | jq '.connector.state'
# Expected: "RUNNING"
# View outbox table
docker exec -it ecommerce-postgres psql -U admin -d orderdb \
-c "SELECT * FROM outbox ORDER BY created_at DESC LIMIT 5;"
# Consume Kafka events
docker exec -it ecommerce-kafka kafka-console-consumer \
--bootstrap-server localhost:9092 \
--topic Order.events \
--from-beginningFor debugging, you can run services with Quarkus Dev Mode:
Authentication Service:
cd authentication-service
./mvnw quarkus:devOrder Service:
cd order-service
./mvnw quarkus:devProduct Service:
cd product-service
./mvnw quarkus:devNotification Service:
cd notification-service
./mvnw quarkus:devThe Order Service implements the Transactional Outbox Pattern using Debezium CDC:
Order Service
β (Transactional Write)
PostgreSQL Outbox Table
β (CDC - Change Data Capture)
Debezium Connector (Kafka Connect)
β (EventRouter SMT)
Kafka Topic: Order.events
β (Consume)
βββ Notification Service (Email/Discord)
βββ Product Service (Stock management)
Benefits:
- β Guaranteed event delivery (at-least-once semantics)
- β Transactional consistency between database and events
- β No event loss even if Kafka is temporarily unavailable
- β Automatic retry and recovery
| Topic | Producer | Consumers | Event Types | Resilience |
|---|---|---|---|---|
| outbox.event.Order | Debezium (from outbox) | Notification, Product | OrderCreated, OrderStatusChanged | 3 retries with exponential backoff |
| outbox.event.Order.dlq | Notification Service | DeadLetterQueueConsumer | Failed events after retries | Manual investigation |
| product-created | Product Service | Notification | ProductCreatedEvent | Default |
| product-updated | Product Service | - | ProductUpdatedEvent | Default |
| product-deleted | Product Service | - | ProductDeletedEvent | Default |
| stock-changed | Product Service | Notification | StockChangedEvent | Default |
| authentication-email | Auth Service | Notification | User registration, password recovery | Default |
Note on outbox.event.Order topic:
- Topic prefix:
outbox(required by Debezium) - Database server name:
outbox(used in topic construction) - Aggregate type:
Order(from outbox table) - Route replacement:
outbox.event.${routedByValue} - Final topic:
outbox.event.Order - Consumers automatically handle double-encoded JSON from Debezium
Resilience Strategy:
- Retry Policy: Notification Service retries failed events 3 times with exponential backoff (2s, 4s, 8s)
- Dead Letter Queue (DLQ): Events that fail after all retries are sent to
outbox.event.Order.dlqfor investigation - No Data Loss: Events are preserved in DLQ for manual reprocessing or troubleshooting
The Product Service still uses direct Kafka publishing for its events. Future improvements may migrate it to the Outbox Pattern as well.
- Framework: Quarkus (Super-fast Subatomic Java)
- Language: Java 21
- Databases: PostgreSQL (with logical replication), MongoDB
- Caching: Redis
- Messaging: Apache Kafka
- CDC: Debezium + Kafka Connect
- Security: SmallRye JWT (ECC), Argon2
- Observability: Prometheus, Grafana, Jaeger (OpenTelemetry)
- Containerization: Docker
curl http://localhost:8081/q/health # Order Service
curl http://localhost:8082/q/health # Product Service
curl http://localhost:8083/q/health # Notification Service
curl http://localhost:8080/q/health # Auth Servicecurl http://localhost:8081/q/metrics # Order Service metricsAccess Prometheus UI: http://localhost:9090
Access Grafana: http://localhost:3000
- User: admin
- Password: (check .env file)
Access Jaeger UI: http://localhost:16686
- Fork the project.
- Create your feature branch (
git checkout -b feature/AmazingFeature). - Commit your changes (
git commit -m 'Add some AmazingFeature'). - Push to the branch (
git push origin feature/AmazingFeature). - Open a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.