Real-world .NET Microservices Architecture
Clean Architecture β’ DDD β’ CQRS β’ Event-Driven β’ Docker β’ Kubernetes β’ GitHub Actions
Created by ProG Coder
π₯ Quick Demo β’ π Support the Project β’ β Give a Star β’ πΊ Watch Tutorials β’ π¬ Facebook Group
If you find this project useful, please star the repository to help us reach more developers!
- Project Overview
- Technology Stack, Design Patterns, Infrastructure & Architecture
- Microservices Overview
- Infrastructure Services
- Web Applications
- Web UI Screenshots
- Project Structure
- Architecture & Design Patterns
- CI/CD Pipeline
- Observability & Monitoring
- Data Infrastructure
- Getting Started
- API Gateway Routes
- Development
- Troubleshooting
- Contributing
- License
https://github.com/huynxtb/progcoder-shop-microservices/tree/main
This repository contains a comprehensive suite of microservices implementing a complete e-commerce platform, including Catalog, Basket, Order, Inventory, Discount, Notification, Search, Report, and Communication services. The platform utilizes a hybrid database strategy with NoSQL (MongoDB, Redis) and Relational databases (PostgreSQL, SQL Server, MySQL).
Services communicate asynchronously via RabbitMQ (Event-Driven Architecture) and are routed through a high-performance YARP API Gateway.
Overall picture of the microservices implementation in the ProG Coder Shop project:
Windows 11- The OS for developing and building this application.WSL2 - Ubuntu OS- The subsystem that helps to run the bash shell on Windows OS.Docker for Desktop (Kubernetes enabled)- The easiest tool to run Docker, Docker Swarm, and Kubernetes on Mac and Windows.Kubernetes/AKS- The app is designed to run on Kubernetes (both locally on "Docker for Desktop" as well as on the cloud with AKS).GitHub Actions- CI/CD automation platform for building, testing, and deploying applications.Helm-β οΈ Under Development - Package manager for Kubernetes applications.
.NET Core 8- .NET Framework and .NET Core, including ASP.NET and ASP.NET Core.Minimal API- Architected to create HTTP APIs with minimal dependencies.Keycloak- Open-source Identity and Access Management solution.YARP- A toolkit for developing high-performance HTTP reverse proxy applications.FluentValidation- Popular .NET validation library for building strongly-typed validation rules.MediatR- Simple, unambitious mediator implementation in .NET.EF Core- Modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.Scrutor- Assembly scanning and decoration extensions for Microsoft.Extensions.DependencyInjection.Serilog- Simple .NET logging with fully-structured events.Carter- Carter is a library that allows Nancy-esque routing for use with ASP.NET Core.Marten- Marten is a .NET document database and event store library.AspNetCore.HealthChecks- Health checks for building services, such as ASP.NET Core.Grpc.AspNetCore- gRPC for .NET, a high-performance RPC framework.MassTransit.RabbitMQ- Distributed application framework for .NET, supporting RabbitMQ.AutoMapper- A high-performance object mapper in .NET.MongoDB.Driver- Official MongoDB .NET Driver.Minio- MinIO .NET Client SDK for Amazon S3 compatible cloud storage.StackExchangeRedis- General purpose Redis client for .NET.Polly- Polly is a .NET resilience and transient-fault-handling library.OpenTelemetry- OpenTelemetry provides observability frameworks for cloud-native software.Quartz.NET- Job scheduling library for .NET.NEST- Official Elasticsearch .NET client for full-text search and analytics.Dapper- Micro-ORM for .NET.SignalR- Library for adding real-time web functionality to apps.Refit- The automatic type-safe HTTP library for .NET Core.Feature Management- Library for feature flags management in .NET.FusionCache- Easy to use, fast and robust hybrid cache with advanced features (Will be applied in User Service soon).
Node.js 18.x- JavaScript runtime built on Chrome's V8 JavaScript engine.ReactJS- A JavaScript library for building user interfaces.Vite- Next generation frontend tooling for fast development.i18next- Internationalization framework.Keycloak-js- JavaScript adapter for Keycloak.Redux Toolkit- The official, opinionated, batteries-included toolset for efficient Redux development.Axios- Promise based HTTP client for the browser and node.js.React Hook Form- Performant, flexible and extensible forms.Formik- Build forms in React, without the tears.Yup- Schema builder for value parsing and validation.Material UI- Move faster with intuitive React UI tools.ApexCharts- Modern & Interactive Open-source Charts.Chart.js- Simple yet flexible JavaScript charting for designers & developers.
- Repository - Abstracts data access logic, providing a collection-like interface for domain objects.
- Unit of Work - Maintains a list of objects affected by a business transaction and coordinates changes.
- Decorator - A structural pattern that allows behavior to be added to individual objects dynamically.
- Strategy - A behavioral pattern that enables selecting an algorithm's behavior at runtime.
- Mediator - Reduces coupling between components by centralizing complex communications and control logic (using MediatR).
- CQRS - Command Query Responsibility Segregation, a pattern that separates read and write operations.
- Saga - A pattern for managing failures, ensuring data consistency across microservices.
- Outbox Pattern - Ensures reliable event publishing in distributed systems.
- Inbox Pattern - Ensures idempotent message processing, preventing duplicate event handling.
- Vertical Slice Architecture - Organizes code by features instead of technical layers.
This project implements modern architectural patterns to ensure scalability, maintainability, and testability.
Most services follow Clean Architecture combined with DDD (Domain-Driven Design) and CQRS (Command Query Responsibility Segregation). This separation of concerns allows for independent evolution of the domain logic and infrastructure.
To minimize complexity and coupling in specific features or smaller services, we utilize Vertical Slice Architecture. Instead of separating by technical layers (Controller, Service, Repository), code is organized by Features (e.g., "AddItemToBasket", "Checkout"). Each slice contains all the logic needed to fulfill a request, from API to Database.
| Service | Port (HTTPS) | gRPC Port | Database | Description |
|---|---|---|---|---|
| Catalog Service | 5001 | 6001 | PostgreSQL (5433) | Product catalog management, categories, brands |
| Basket Service | 5006 | - | MongoDB (27018) + Redis (6380) | Shopping cart and session management |
| Order Service | 5005 | 6005 | SQL Server (1434) | Order processing and management |
| Inventory Service | 5002 | 6002 | MySQL (3307) | Stock and inventory management |
| Discount Service | 5004 | 6004 | PostgreSQL (5433) | Coupons, promotions, and discount rules |
| Notification Service | 5003 | 6003 | PostgreSQL (5433) | Email/SMS notifications |
| Report Service | 5007 | 6007 | PostgreSQL (5433) | Analytics, dashboards, and reporting |
| Search Service | 5008 | - | Elasticsearch (9200) | Full-text product search |
| Communication Service | 5009 | - | PostgreSQL (5433) | Webhooks and external integrations |
| Component | Port(s) | Purpose | Access URL | Default Credentials |
|---|---|---|---|---|
| PostgreSQL | 5433 | Relational database for multiple services | localhost:5433 |
postgres / 123456789Aa |
| MongoDB | 27018 | Document database for Basket service | localhost:27018 |
mongodb / 123456789Aa |
| MySQL | 3307 | Relational database for Inventory | localhost:3307 |
root / 123456789Aa |
| SQL Server | 1434 | Relational database for Order service | localhost:1434 |
sa / 123456789Aa |
| Redis | 6380 | Cache and session storage | localhost:6380 |
Password: 123456789Aa |
| RabbitMQ | 5673, 15673 | Message broker for event-driven communication | http://localhost:15673 | admin / 123456789Aa |
| Keycloak | 8080 | Identity and Access Management | http://localhost:8080 | admin / admin |
| MinIO | 9000, 9001 | S3-compatible object storage | http://localhost:9001 | minioadmin / minioadmin |
| Elasticsearch | 9200 | Search engine and analytics | http://localhost:9200 | elastic / elastic123 |
| Prometheus | 9090 | Metrics collection and monitoring | http://localhost:9090 | - |
| Grafana | 3000 | Metrics visualization and dashboards | http://localhost:3000 | admin / admin |
| Tempo | 3200 | Distributed tracing backend | http://localhost:3200 | - |
| Loki | 3100 | Log aggregation system | http://localhost:3100 | - |
| Promtail | 1514, 9080 | Log collection agent | - | - |
| OpenTelemetry Collector | 4317, 8888 | Telemetry data collection | http://localhost:8888 | - |
| Portainer | 9000, 9443 | Container management UI | http://localhost:9443 | admin / (set on first run) |
| MailHog | 1025, 8025 | Email testing tool | http://localhost:8025 | - |
| cAdvisor | - | Container metrics | - | - |
| Application | Port | Technology Stack | Purpose | Access URL |
|---|---|---|---|---|
| App.Admin | 3001 | React + Vite + TailwindCSS | Admin management interface | http://localhost:3001 |
| Store Frontend | 3002 | React + Vite + Bootstrap | Customer shopping interface | http://localhost:3002 |
| YARP API Gateway | 15009 | ASP.NET Core + YARP | API Gateway and reverse proxy | http://localhost:15009 |
All screenshots are stored in assets/imgs/screenshots.
progcoder-shop-microservices/
βββ src/
β βββ Services/ # Backend Microservices
β β βββ Basket/ # Shopping cart service
β β β βββ Api/ # REST API endpoints
β β β βββ Core/ # Domain, Application layers
β β β βββ Worker/ # Background workers (Outbox)
β β βββ Catalog/ # Product catalog service
β β β βββ Api/ # REST API + gRPC
β β β βββ Core/ # Domain, Application layers
β β β βββ Worker/ # Background workers (Outbox, Consumer)
β β βββ Communication/ # Webhooks and messaging
β β βββ Discount/ # Coupons and promotions
β β βββ Inventory/ # Stock management
β β βββ Notification/ # Email/SMS notifications
β β βββ Order/ # Order processing
β β βββ Report/ # Analytics and reporting
β β βββ Search/ # Product search (Elasticsearch)
β βββ Apps/
β β βββ App.Admin/ # App.Admin (React)
β β βββ App.Store/ # E-commerce storefront (React)
β βββ ApiGateway/
β β βββ YarpApiGateway/ # YARP reverse proxy
β βββ JobOrchestrator/
β β βββ App.Job/ # Scheduled background jobs (Quartz)
β βββ Shared/
β βββ BuildingBlocks/ # CQRS, Behaviors, Pagination
β βββ Common/ # Extensions, Helpers, Models
β βββ Contracts/ # gRPC proto definitions
β βββ EventSourcing/ # Integration events
βββ config/ # Configuration files
β βββ prometheus/ # Prometheus config and alert rules
β βββ grafana/ # Grafana dashboards and datasources
β βββ loki/ # Loki configuration
β βββ tempo/ # Tempo configuration
β βββ otel-collector/ # OpenTelemetry Collector config
β βββ keycloak/ # Keycloak providers
β βββ rabbitmq/ # RabbitMQ plugins
βββ assets/ # Static assets
β βββ imgs/ # Architecture diagrams and screenshots
β βββ postman collections/ # API testing collections
βββ local-data/ # Persistent data volumes
βββ scripts/ # Dev-utility shell scripts (migrations)
βββ docker-compose.infrastructure.yml # Infrastructure services
βββ docker-compose.yml # Application services
βββ Makefile # `make` shortcuts for common commands
βββ README.md # This file
The project follows Clean Architecture principles with clear separation of concerns:
- Domain Layer: Contains business entities, value objects, domain events, and business rules. No dependencies on other layers.
- Application Layer: Contains business logic, CQRS commands/queries, DTOs, and interfaces. Depends only on Domain layer.
- Infrastructure Layer: Contains data access, external service integrations, and infrastructure concerns. Implements interfaces from Application layer.
- API Layer: Contains REST API endpoints using Carter, request/response models, and API routing.
- Aggregates: Root entities that maintain consistency boundaries
- Value Objects: Immutable objects representing domain concepts
- Domain Events: Events raised within the domain to communicate state changes
- Repositories: Abstraction for data access with interface in Application and implementation in Infrastructure
- Commands: Write operations that modify state (using MediatR)
- Queries: Read operations that return data without side effects
- Handlers: Separate handlers for commands and queries
- Validators: FluentValidation for command/query validation
- Domain Events: Internal events within a service
- Integration Events: Cross-service communication via RabbitMQ
- Outbox Pattern: Ensures reliable event publishing using outbox tables
- Event Handlers: MassTransit consumers for processing integration events
Distributed transaction management across multiple services using choreography-based sagas with event-driven coordination.
The project uses GitHub Actions for continuous integration and deployment:
- Build Workflow: Automated building and testing of services
- Docker Image Publishing: Automated image building and pushing to Docker Hub
- Multi-service Deployment: Coordinated deployment across all microservices
- Kubernetes Deployment:
β οΈ Under Development
- OpenTelemetry: Instrumentation for all services
- Tempo: Distributed tracing backend
- Jaeger Protocol: Trace visualization and analysis
- Prometheus: Collects metrics from all services, databases, and message brokers.
- Grafana: Provides beautiful, pre-configured dashboards for real-time monitoring:
- Service Health: CPU, Memory, Request latency, and Error rates.
- Infrastructure: Docker container stats (via cAdvisor) and System resources.
- Business Metrics: Real-time order stats, revenue, and active users.
- cAdvisor: Container resource usage metrics.
- ASP.NET Core Health Checks: Exposes health status for Kubernetes probes.
- Loki: Horizontally-scalable, highly-available, multi-tenant log aggregation system.
- Promtail: The agent which ships the contents of local logs to a private Grafana Loki instance.
- Grafana: Allows you to query logs using LogQL and correlate them with metrics and traces.
- Serilog: Structured logging in all services, ensuring logs are rich with context (TraceId, SpanId) for distributed tracing correlation.
- Prometheus Alertmanager: Alert routing and management
- Configured alerts for:
- Service downtime
- High error rates
- Database connection failures
- Message queue backlogs
- Object storage solution designed for high performance and scalability
- Stores product images, documents, and other unstructured data
- S3-compatible API for easy integration
- Full-text search engine for product catalog
- Powered by Search Service for fast product discovery
- Supports fuzzy search, filters, and faceted navigation
- In-memory cache for session management
- Shopping cart persistence
- Distributed caching for frequently accessed data
- Event-driven communication between services
- Reliable message delivery with acknowledgments
- Dead-letter queues for failed messages
- Message persistence for durability
Before running the project, ensure you have the following installed:
- Docker Desktop (with Kubernetes enabled) - Download
- .NET 8 SDK - Download
- Node.js 18+ - Download
- Git - Download
- Create environment file (Infrastructure uses environment variables):
# Copy the sample environment file to .env (skips if .env already exists)
make env
# Edit .env and configure your custom ports and credentials if neededNote: The .env.sample file contains all required environment variables with default values. Key configurations include:
- Database ports (custom ports to avoid conflicts: PostgreSQL 5433, MongoDB 27018, MySQL 3307, SQL Server 1434)
- Database credentials
- Message broker settings (RabbitMQ on ports 5673/15673)
- Identity provider (Keycloak on port 8080)
- Monitoring stack ports
- Object storage (MinIO on ports 9000/9001)
Run the entire system with Docker Compose - Best for testing and production deployment:
# Clone the repository
git clone <repository-url>
cd progcoder-shop-microservices
# Copy and configure environment variables
make env
# Option 1: Build all images in parallel, then start services
make build
make up
# Option 2: Build and start services in one command
make start
# Check all services are running
make ps
# View logs
make logs
# View logs for specific service
make logs-[service-name]
# Stop all services
make down
# Stop and remove volumes (clean slate)
make down-v
# Restart all services
make restart
# Rebuild and restart all services
make rebuildAfter starting, access:
- App.Admin: http://localhost:3001
- App.Store: http://localhost:3002
- API Gateway: http://localhost:15009
- Keycloak: http://localhost:8080
- Grafana: http://localhost:3000
- RabbitMQ Management: http://localhost:15673
For development, run services individually to debug and modify code:
# Start infrastructure services (databases, message broker, monitoring, etc.)
make infra-up
# Wait for all services to be healthy (check with)
make infra-ps
# View logs if needed
make infra-logs-[service-name]Option A: Apply Existing Migrations (Recommended for first-time setup)
Use this to apply all existing migrations to your databases without creating new ones:
make migrateThis script will automatically:
- Install dotnet-ef tool if needed
- Apply all pending migrations for Inventory service (MySQL)
- Apply all pending migrations for Order service (SQL Server)
- Show a summary of results
Option B: Create New Migrations (For developers making schema changes)
Use this when you need to create a new migration after modifying entities:
make migration-addThis script will:
- Prompt you to select a service
- Ask for a migration name
- Create the migration
- Automatically apply it to the database
- Open Keycloak Admin Console: http://localhost:8080
- Login with:
admin/admin - Create realm:
prog-coder-realm - Create client:
prog-coder-client-id - Configure client settings and obtain client secret
- Update
appsettings.jsonin each service with Keycloak settings
Each service can be started individually. Open separate terminal windows:
make run-catalog-api # Catalog Service
make run-basket-api # Basket Service
make run-order-api # Order Service
make run-inventory-api # Inventory Service
make run-discount-api # Discount Service
make run-notification-api # Notification Service
make run-report-api # Report Service
make run-search-api # Search Service
make run-communication-api # Communication Service
make run-api-gateway # API Gatewaymake run-catalog-worker # Catalog Outbox Worker
make run-basket-worker # Basket Outbox Worker
make run-order-worker # Order Outbox Worker
make run-inventory-worker # Inventory Outbox Worker
make run-notification-worker # Notification Consumer Worker
make run-search-worker # Search Consumer Workermake run-app-admin # App Admin - Access at: http://localhost:3001
make run-app-store # App Store - Access at: http://localhost:3002make run-job-orchestratorAfter starting all services, you can access:
- App.Admin: http://localhost:3001
- App.Store: http://localhost:3002
- API Gateway: http://localhost:15009
- Catalog API: http://localhost:5001/swagger
- Basket API: http://localhost:5006/swagger
- Order API: http://localhost:5005/swagger
- Inventory API: http://localhost:5002/swagger
- Discount API: http://localhost:5004/swagger
- Notification API: http://localhost:5003/swagger
- Report API: http://localhost:5007/swagger
- Search API: http://localhost:5008/swagger
- Communication API: http://localhost:5009/swagger
- Keycloak: http://localhost:8080 (admin / admin)
- RabbitMQ Management: http://localhost:15673 (admin / 123456789Aa)
- MinIO Console: http://localhost:9001 (minioadmin / minioadmin)
- Grafana: http://localhost:3000 (admin / admin)
- Prometheus: http://localhost:9090
- Portainer: http://localhost:9443
- MailHog: http://localhost:8025
- Elasticsearch: http://localhost:9200 (elastic / elastic123)
| Service | Username | Password |
|---|---|---|
| Keycloak | admin | admin |
| Grafana | admin | admin |
| RabbitMQ | admin | 123456789Aa |
| PostgreSQL | postgres | 123456789Aa |
| MongoDB | mongodb | 123456789Aa |
| MySQL | root | 123456789Aa |
| SQL Server | sa | 123456789Aa |
| MinIO | minioadmin | minioadmin |
| Elasticsearch | elastic | elastic123 |
| Redis | - | 123456789Aa |
The YARP API Gateway provides unified access to all microservices:
| Route | Target Service | Example |
|---|---|---|
/catalog-service/** |
Catalog Service (5001) | /catalog-service/api/products |
/basket-service/** |
Basket Service (5006) | /basket-service/api/baskets |
/order-service/** |
Order Service (5005) | /order-service/api/orders |
/inventory-service/** |
Inventory Service (5002) | /inventory-service/api/inventory |
/discount-service/** |
Discount Service (5004) | /discount-service/api/coupons |
/notification-service/** |
Notification Service (5003) | /notification-service/api/notifications |
/report-service/** |
Report Service (5007) | /report-service/api/reports |
/search-service/** |
Search Service (5008) | /search-service/api/search |
/communication-service/** |
Communication Service (5009) | /communication-service/api/webhooks |
You can run services individually for development, with hot reload:
make watch SERVICE=[ServiceName]# Run all tests
make test
# Run tests for a specific service
make test-svc SERVICE=[ServiceName]# Add migration
make ef-add SERVICE=[ServiceName] NAME=[MigrationName]
# Apply migration
make ef-update SERVICE=[ServiceName]This approach helps avoid Docker daemon overload and makes debugging easier:
# Step 1: Start infrastructure services first
make build-infra-svc
# Step 2: Build and run gRPC services
make build-grpc
# Step 3: Build and run API services
make build-api-svc
# Step 4: Build and run Workers
make build-workers
# Step 5: Build and run API Gateway and Apps
make build-gateway-appsThis method is faster but requires sufficient system resources:
# Build all images in parallel, then start all services
make build-all
# Or combine both steps
make start# Build specific service
make build-[service-name]
# Build and start specific service
make up-[service-name]# Force rebuild all images without cache
make build-nocache
# Rebuild and restart all services
make rebuild-
Port Conflicts: Ensure no other services are using the configured ports
- Check with:
netstat -ano | findstr :[PORT](Windows) orlsof -i :[PORT](Mac/Linux)
- Check with:
-
Database Connection Errors:
- Verify all database containers are running:
docker ps - Check database logs:
docker logs [container-name]
- Verify all database containers are running:
-
Keycloak Configuration:
- Ensure realm and client are properly configured
- Verify client secret matches in service configurations
-
RabbitMQ Connection Issues:
- Check RabbitMQ is running: http://localhost:15673
- Verify credentials in service configurations
-
Docker Build Timeout or DNS Errors:
- If you see
i/o timeoutorfailed to do request, it's likely a Docker daemon network issue - Solution 1: Restart Docker Desktop
- Solution 2: Check Docker Desktop proxy settings (Settings β Resources β Proxies)
- Solution 3: Clean up Docker cache:
docker system prune -af - Solution 4: Build services incrementally (see Method 1 in Building Docker Images section)
- If you see
-
Docker Build Context Too Large:
- Ensure
.dockerignorefile exists and excludes unnecessary files - The
.dockerignoreshould exclude:docker-volumes/,config/,assets/,node_modules,*.log,*.sock
- Ensure
-
Worker Services Failing to Start:
- Error:
Framework 'Microsoft.AspNetCore.App' not found - Solution: Ensure all worker Dockerfiles use
mcr.microsoft.com/dotnet/aspnet:8.0(notruntime:8.0)
- Error:
# Check container status
make ps
# View logs for all services
make logs
# View logs for specific service
make logs-[service-name]
# Restart a service
make restart-[service-name]
# Stop all services
make down
# Stop all services and remove volumes (clean slate)
make down-v
# Remove stopped containers and unused images
make prune
# Remove all unused images, containers, networks, and volumes
make prune-all
# Check Docker disk usage
make df
# View running containers
docker ps
# View all containers (including stopped)
docker ps -a
# Execute command in running container
docker exec -it [container-name] bash
# Check container resource usage
make stats# Check container status
make infra-ps
# View logs
make infra-logs-[service-name]
# Restart a service
make infra-restart-[service-name]
# Stop all services
make infra-down
# Remove volumes (clean slate)
make infra-down-vWe welcome community contributions! We use GitHub issues to track bugs and feature requests, and pull requests to manage contributions. See the contribution information for more details.
Code released under the MIT License
- Huy Nguyen - Initial work - huynxtb
See also the list of contributors who participated in this project.
Join our community to stay updated and connect with other developers:
- π¬ Facebook Group: ProG Coder Community - Get the latest updates, ask questions, and share your experience
- πΊ YouTube Channel: ProG Coder - Video tutorials and coding sessions
- π Website: https://www.progcoder.com - Articles, resources, and more
- Postman Collection: See
assets/postman collections/for API testing - Architecture Diagrams: See
assets/imgs/for visual references





