This project implements a microservices-based e-commerce system using Go, following CQRS (Command Query Responsibility Segregation) and Hexagonal Architecture principles. It consists of four core services: User, Product, Order, and Notification, communicating via gRPC and Kafka.
- User Service: Manages user authentication (registration, login, JWT generation) and user profiles.
- Product Service: Manages product information, including stock. Utilizes PostgreSQL for persistence and Redis for caching. Subscribes to order events to update stock.
- Order Service: Handles order creation and management. Communicates with User service via gRPC for user validation and publishes order events to Kafka.
- Notification Service: Sends email/SMS notifications based on events consumed from Kafka.
The system is designed with the following key architectural patterns:
- Microservices: Independent, loosely coupled services.
- CQRS (Command Query Responsibility Segregation): Separates read and write models within each service for better scalability and maintainability.
- Hexagonal Architecture (Ports & Adapters): Ensures business logic is independent of external concerns (databases, UI, message brokers).
- gRPC: High-performance, contract-first communication for synchronous inter-service calls.
- Kafka: Event-driven architecture for asynchronous communication and decoupling services.
- API Gateway (Traefik): Centralized entry point for external clients, handling routing, load balancing, and security (JWT validation, Rate Limiting).
- Observability: Integrated logging (slog), metrics (Prometheus), and distributed tracing (OpenTelemetry/Jaeger).
- Backend: Go (GoLang)
- Databases: PostgreSQL, Redis
- Message Broker: Apache Kafka
- API Gateway: Traefik
- Inter-service Communication: gRPC
- Containerization: Docker
- Orchestration: Kubernetes
- CI/CD: GitHub Actions
- Observability: Prometheus, Grafana, Jaeger
- Serialization: Protocol Buffers (
.proto)
Before you begin, ensure you have the following installed:
- Go (1.21 or higher)
- Docker Desktop (includes Docker Engine and Docker Compose)
- Protocol Buffers Compiler (
protoc) and Go plugins:Ensurego install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
$GOPATH/binis in your system'sPATH. - kubectl (for Kubernetes deployment)
This section guides you through setting up and running the entire system locally using Docker Compose.
From the project root directory, run:
docker-compose up -dThis command will start:
postgres(database for all services)redis(cache for product service)kafka(message broker)traefik(API Gateway)jaeger(distributed tracing)prometheus(metrics collection)grafana(metrics visualization)
You can access:
- Traefik Dashboard:
http://localhost:8080/dashboard/ - Prometheus:
http://localhost:9090/ - Grafana:
http://localhost:3000/(default user/pass:admin/admin) - Jaeger UI:
http://localhost:16686/
For each service, navigate to its directory and run protoc to generate Go code from .proto files.
Note: This step assumes protoc is installed and configured correctly.
# For users-service
cd users-service
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative api/proto/users.proto
cd ..
# For products-service
cd products-service
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative api/proto/products.proto
cd ..
# For orders-service
# First, copy users.proto as orders-service depends on it
copy users-service\api\proto\users.proto orders-service\api\proto\users.proto # Use 'cp' on Linux/macOS
cd orders-service
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative api/proto/orders.proto
cd ..
# For notification-service
cd notification-service
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative api/proto/notification.proto
cd ..Open a new terminal for each service. Navigate to the service's root directory and run:
# For users-service
cd users-service
go mod tidy # Ensure dependencies are up-to-date
go run ./cmd/users-service# For products-service
cd products-service
go mod tidy
go run ./cmd/products-service# For orders-service
cd orders-service
go mod tidy
go run ./cmd/orders-service# For notification-service
cd notification-service
go mod tidy
go run ./cmd/notification-serviceOnce all services are running, you can interact with them via the Traefik API Gateway at http://localhost/api.
Example Endpoints (using curl or Postman):
- Create User (POST):
http://localhost/api/users{ "username": "testuser", "email": "test@example.com", "password": "password123" } - Login User (POST):
http://localhost/api/login(This will return a JWT token){ "email": "test@example.com", "password": "password123" } - Get User by ID (GET):
http://localhost/api/users/{user_id} - Get Product by ID (GET):
http://localhost/api/products/{product_id} - Create Order (POST):
http://localhost/api/orders{ "user_id": "UUID_OF_EXISTING_USER", "items": [ { "product_id": "UUID_OF_EXISTING_PRODUCT", "quantity": 2, "price": 10.50 } ] }
The k8s/ directory contains Kubernetes manifests for deploying the services.
Ensure your kubectl is configured to connect to your Kubernetes cluster.
kubectl apply -f k8s/users-service.yaml
kubectl apply -f k8s/products-service.yaml
kubectl apply -f k8s/orders-service.yaml
kubectl apply -f k8s/notification-service.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secret.yaml
kubectl apply -f k8s/ingress.yamlYou will need a mechanism to run database migrations (e.g., using a dedicated migration job in Kubernetes or a tool like golang-migrate). The SQL files are located in [service-name]/migrations/.
The .github/workflows/ci.yml file defines a GitHub Actions workflow that:
- Builds all Go services.
- Builds Docker Images for each service and pushes them to a Docker registry (requires
DOCKER_USERNAMEandDOCKER_PASSWORDsecrets configured in GitHub). - Deploys the services to a Kubernetes cluster (requires
KUBE_CONFIGsecret configured in GitHub with your cluster's kubeconfig).
- Comprehensive Testing: Add unit, integration, and end-to-end tests for all services.
- Full JWT Validation: Implement robust JWT validation middleware in Traefik or a dedicated authentication service.
- Error Handling: More granular error types and consistent error responses.
- Database Migrations: Implement an automated database migration tool.
- API Documentation: Generate and host interactive Swagger UI from OpenAPI specification.
- Advanced Observability: Custom Grafana dashboards, more detailed metrics, and alerts.
- Scalability: Implement horizontal scaling for services and infrastructure components.
- Security: Implement mTLS for inter-service communication, more robust secret management.
- Configuration Management: Use a dedicated configuration service (e.g., HashiCorp Consul, Kubernetes ConfigMaps/Secrets with external secrets operator).