ERP Microservices Backend — .NET 9 · PostgreSQL · Docker · YARP · MassTransit · Orchestration
This repository contains a modular, production-grade ERP backend built with .NET 9, following Clean Architecture and microservices best practices. Each bounded context (Catalog, Procurement, etc.) is implemented as an independent service with its own API, Application, Domain, and Infrastructure projects.
- Tech Stack: .NET 9, ASP.NET Core, PostgreSQL, EF Core 9, MassTransit (RabbitMQ), YARP (API Gateway), Docker
- Architecture: Clean Architecture, CQRS, DDD, Outbox Pattern, Database-per-Service
DotnetCoreMicroService.sln
├─ Src/
│ ├─ BuildingBlocks/
│ │ ├─ Persistence/
│ │ ├─ Messaging/
│ │ └─ Web/
│ ├─ Services/
│ │ ├─ Catalog/
│ │ │ ├─ Catalog.Api/
│ │ │ ├─ Catalog.Application/
│ │ │ ├─ Catalog.Domain/
│ │ │ └─ Catalog.Infrastructure/
│ │ └─ ... (other services: procurement, inventory, etc.)
│ └─ contracts/ (OpenAPI specs, DTOs)
├─ Deploy/
│ └─ compose/
│ ├─ infra.yml
│ └─ dev.yml
└─ Tests/
- Microservice per bounded context: Each service is fully isolated.
- Database-per-service: One Postgres instance, each service owns its schema and migrations.
- No shared domain code: Only contracts/utilities in
BuildingBlocks. - Independently deployable: Each service can be built and run on its own.
- Api: HTTP endpoints, DI, health checks, Swagger, logging, YARP gateway.
- Application: CQRS handlers, validation, orchestration, MediatR.
- Domain: Entities, value objects, domain services, business rules.
- Infrastructure: EF Core DbContext, migrations, repositories, outbox, messaging.
- BuildingBlocks: Shared technical utilities (never domain logic).
docker compose -f Docs/Compose/infra.yml up -dOpen PgAdmin in the browser: http://localhost:8081
- Login | Email Address:
admin@local.com| Password:admin - Register Database | Host:
postgres| Post:5432| Username:serviceadmin| Database:postgres| Password:123qwe
Apply Migration:
dotnet ef database update -p Src/Services/Catalog/Catalog.Infrastructure -s Src/Services/Catalog/Catalog.Api
dotnet ef database update -p Src/Services/Procurement/Procurement.Infrastructure -s Src/Services/Procurement/Procurement.Api
dotnet ef database update -p Src/Services/UserManagement/UserManagement.Infrastructure -s Src/Services/UserManagement/UserManagement.Apidotnet watch --project Src/Services/Catalog/Catalog.Apidotnet watch --project Src/Services/Procurement/Procurement.Apidotnet run --project Src/Gateway.Apidotnet ef migrations add -p Src/Services/Catalog/Catalog.Infrastructure -s Src/Services/Catalog/Catalog.Api
dotnet ef database update -p Src/Services/Catalog/Catalog.Infrastructure -s Src/Services/Catalog/Catalog.ApiYou can run the API Gateway and multiple microservices at once using Visual Studio:
- Right-click the solution in Solution Explorer and select Set Startup Projects…
- Choose Multiple startup projects.
- For each project you want to run (e.g.,
Gateway.Api,Catalog.Api,Procurement.Api), set the Action to Start. - Click OK.
- Press F5 or click Start to launch all selected services together.
-
Direct service endpoints:
- List products:
GET http://localhost:5101/v1/products - Product detail:
GET http://localhost:5101/v1/products/{id} - List categories:
GET http://localhost:5101/v1/categories - Category detail:
GET http://localhost:5101/v1/categories/{id}
- List products:
-
Via API Gateway:
- List products:
GET http://localhost:5000/api/catalog/products - Product detail:
GET http://localhost:5000/api/catalog/products/{id} - List categories:
GET http://localhost:5000/api/catalog/categories - Category detail:
GET http://localhost:5000/api/catalog/categories/{id}
- List products:
The API Gateway (
Gateway.Api) uses YARP to route/api/catalog/{**catch-all}to/v1/{**catch-all}on the Catalog service. SeeGateway.Api/appsettings.jsonfor details.
-
Direct service endpoints:
- List suppliers:
GET http://localhost:5102/v1/suppliers - Supplier detail:
GET http://localhost:5102/v1/suppliers/{id} - List supplier products:
GET http://localhost:5102/v1/supplier-products - Supplier product detail:
GET http://localhost:5102/v1/supplier-products/{supplierId}/{productId}
- List suppliers:
-
Via API Gateway:
- List suppliers:
GET http://localhost:5000/api/procurement/suppliers - Supplier detail:
GET http://localhost:5000/api/procurement/suppliers/{id} - List supplier products:
GET http://localhost:5000/api/procurement/supplier-products - Supplier product detail:
GET http://localhost:5000/api/procurement/supplier-products/{supplierId}/{productId}
- List suppliers:
The API Gateway (
Gateway.Api) uses YARP to route/api/procurement/{**catch-all}to/v1/{**catch-all}on the Procurement service. SeeGateway.Api/appsettings.jsonfor details.
- All external traffic goes through the Gateway (
Gateway.Api). - Routes like
/api/catalog/...or/api/procurement/...are mapped to internal service endpoints. - See
Gateway.Api/appsettings.jsonfor route config.
- Follow Clean Architecture and DDD boundaries.
- Do not share domain code between services.
- Add new features in the appropriate layer and project.
- See
copilot-instructions.mdandArchitecture.mdfor detailed guidelines.
