A professional .NET microservices architecture along with justifications. I'll also include additional considerations where necessary.
1. Authentication
Best Choice: OIDC (OpenID Connect)
Justification: OIDC is built on top of OAuth2 and provides identity verification along with authorization. It is the industry standard for securing APIs and supports SSO (Single Sign-On) across microservices. OAuth2 alone lacks an identity layer, while Basic Authentication is insecure and unsuitable for modern microservices.
👉 Additional Consideration: Use IdentityServer, Auth0, or Azure AD B2C as an OIDC provider.
2. API Gateway
Best Choice: YARP
Justification: YARP (Yet Another Reverse Proxy) is a high-performance, modern, and extensible API Gateway designed for .NET. It supports dynamic route updates, better integration with Kubernetes, and lower overhead compared to Ocelot.
👉 When to Use Ocelot?
Ocelot is a good choice for simpler scenarios but lacks performance optimization for large-scale systems.
3. Database Strategy
Best Choice: Per Service Database
Justification: Each microservice should have its own database to ensure loose coupling, scalability, and data ownership. A shared database contradicts the microservices principle and creates a single point of failure.
4. Database Provider
Best Choice: MS SQL & PostgreSQL
Justification:
- MS SQL – Best for enterprise-level systems with strong ACID compliance.
- PostgreSQL – Open-source, excellent for scalability and JSON support (can replace NoSQL in some cases).
- MongoDB – Only for services needing high flexibility, schema-less storage, or event sourcing.
👉 Recommendation: Allow multiple providers based on service needs.
5. ORM
Best Choice: Entity Framework Core (EF Core)
- Justification: EF Core provides ease of use, code-first approach, and multi-database support. For high-performance scenarios, Dapper can be used as a complement.
👉 Additional Consideration: Use Dapper for read-heavy microservices.
6. API Type
Best Choice: REST (Primary) & GraphQL (Selective)
Justification:
- REST – Standard, well-supported, and easier for public APIs.
- GraphQL – Useful for complex queries and reducing over-fetching in micr oservices.
👉 Recommendation: Use GraphQL selectively for services requiring flexible data fetching.
7. API Documentation
Best Choice: OpenAPI (Swagger)
Justification: OpenAPI is widely adopted, automatically generated, and integrates well with .NET and API Gateway.
👉 Scalar is optional unless you're using GraphQL.
8. Coding Practices
Best Choice: Clean Architecture + MediatR + Repository Pattern
Justification:
- Clean Architecture – Ensures separation of concerns and testability.
- MediatR – Helps in CQRS, reducing dependencies, and improving maintainability.
- Reposi tory Pattern – Abstracts the database layer.
👉 Alternative: Consider Vertical Slice Architecture for better microservices modularity.
9. Testing Strategy
Best Choice:
Unit Testing → NUnit (more flexible than MSTest)
BDD → SpecFlow (for behavior-driven development)
Performance Testing → JMeter
10. Inter-Service Communication
Best Choice: Combination of REST, Message Queue, and gRPC
Justification:
- REST → For standard synchronous service calls.
- Message Queue (Kafka / RabbitMQ) → For event-driven architecture and decoupling services.
- gRPC → For high-performance inter-service communication, especially interna l services.
👉 Recommendation: Use Kafka for event-driven systems and RabbitMQ for task queues.
11. Scheduled Services
Best Choice: Hangfire + MongoDB
Justification:
- Hangfire is great for background job processing.
- MongoDB s tores Hangfire jobs efficiently without requiring SQL.
12. Caching
Best Choice: Redis
Justification:
- Redis is fast, scalable, and supports distributed caching.
- Mong oDB caching is less efficient compared to Redis.
13. Logging
Best Choice: Serilog
Justification:
- Serilog is structured logging, supports Elasticsearch, and integrates well with .NET microservices.
- NLog an d log4net are alternatives but less popular for modern architectures.
👉 Recommendation: Use Serilog + Elastic Stack (ELK) or Seq for centralized logging.
14. Service Monitoring
Best Choice: OpenTelemetry + Jaeger + Basic Health Monitoring
Justification:
- OpenTelemetry – Standardized tracing and metrics collection.
- Jaeger – Best for distributed tracing.
- Basic Health Monitoring – Use .NET HealthChecks for simple readiness and liveness probes.
15. CI/CD
Best Choice: Docker & Kubernetes
Justification: Kubernetes allows auto-scaling, self-healing, and efficient microservice deployment. Docker ensures consistency across environments.
👉 Additional Consideration: Use Helm charts for managing Kubernetes deployments.
16. Retry Policy
Best Choice: Polly
Justification: Polly provides resilience for microservices with features like:
- Retry policy
- Circuit breaker
- Bulkhead isolation
- Timeo ut handling
👉 Recommendation: Implement Polly middleware in API Gateway and microservices.
17. Secrets Management
Why? Avoid hardcoding sensitive information (DB credentials, API keys).
Tools:
- Azure Key Vault (if using Azure)
- AWS Secrets Manager (if using AWS)
- Vau lt by HashiCorp (for self-hosted solutions)
Final Notes:
This architecture ensures scalability, resilience, and maintainability.
Adopt best practices like CQRS, Domain-Driven Design (DDD) for complex domains.
Security: Ensure API Gateway handles authentication & authorization centrally.
Observability: Implement structured logging & monitoring to diagnose issues efficiently.
Top comments (5)
EF is the worst for ASP.net. Its Unit-of-work implementation is contrary to the definition of a RESTful service and only gets in the way.
EF is a popular ORM tool that streamlines data access, yet its Unit-of-Work model also can seem limiting in specific RESTful service contexts. EF's approach helps in uniform transaction management, which is crucial for preserving data integrity during complex operations.
Do you know that dev.to's guidelines for using AI prohibits the use of AI in comments? If I had the courtesy of writing my own comment, you have that same courtesy back.
Ok, since I won't be getting a response back (that isn't generated by AI), here's the final response: The AI is wrong in this comment. RESTful operations usually limit themselves to a single entity. After all, each entity gets its own URI, and by definition of REST, the entities are written in isolation of other entities.
Because isolation of entities is part of the definition of REST, I don't need to preserve data integrity with a Unit-of-work pattern that has zero value to REST.
If the AI is talking about anything else when it uses the vague term "uniform transaction management", I cannot imagine what it could be. Most DBRMS engines (or all?) provide ACID transactions. EF is not the Mesiah of transaction management. The comment is plain wrong. I can do proper transaction handling with ADO.Net and save myself the horrors that EF comes with.
Some comments have been hidden by the post's author - find out more