Introduction
Modern cloud-native applications often consist of multiple services working together. These services require consistent configuration for logging, health checks, telemetry, resilience, and service discovery. Configuring each service individually can become repetitive and increase the risk of inconsistencies.
.NET Aspire simplifies this process by introducing Service Defaults, a shared project that centralizes common configurations across all services in your application. Instead of repeating the same setup in every microservice, you configure it once and reuse it everywhere.
In this article, you'll learn what .NET Aspire Service Defaults are, why they're important, how they work, and how to use them effectively in your .NET applications.
What Are .NET Aspire Service Defaults?
Service Defaults is a reusable project created when you build a .NET Aspire application. It contains common configurations that are automatically shared across your services.
Instead of configuring features such as OpenTelemetry, health checks, and service discovery separately for each project, you configure them once in the Service Defaults project.
This approach helps maintain consistency across your distributed applications.
Why Use Service Defaults?
As applications grow, managing shared configurations becomes more challenging.
Service Defaults provide several advantages:
Centralized configuration
Consistent application behavior
Reduced code duplication
Faster project setup
Easier maintenance
Better observability
Simplified cloud-native development
By standardizing common configurations, development teams can focus more on business logic and less on infrastructure setup.
Typical Aspire Solution Structure
A typical .NET Aspire solution includes multiple projects.
MyAspireApp
│
├── AppHost
├── ServiceDefaults
├── ProductService
├── OrderService
├── InventoryService
└── WebFrontend
In this structure:
AppHost manages the application.
ServiceDefaults contains shared configurations.
Service projects implement business functionality.
WebFrontend provides the user interface.
Every service references the Service Defaults project.
What's Included in Service Defaults?
The Service Defaults project typically configures several common features, including:
These features are automatically shared across participating services.
Adding Service Defaults to a Project
In each service, call the extension method during application startup.
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
This single line applies the shared configuration defined in the Service Defaults project.
Mapping Default Endpoints
After configuring shared services, map the default endpoints.
var app = builder.Build();
app.MapDefaultEndpoints();
app.Run();
These endpoints often include health checks and diagnostics that are useful during development and deployment.
Health Checks
Health checks are an important part of cloud-native applications.
With Service Defaults, enabling health endpoints becomes much simpler.
Benefits include:
Container readiness checks
Kubernetes health monitoring
Azure deployment validation
Service availability monitoring
Instead of configuring health checks in every project, they become part of the shared setup.
Centralized Logging
Consistent logging is essential for troubleshooting distributed applications.
Service Defaults help standardize logging behavior across services by applying the same configuration everywhere.
This makes it easier to:
Search application logs
Diagnose production issues
Correlate requests between services
Monitor application behavior
A unified logging strategy improves both development and operations.
OpenTelemetry Integration
Distributed applications generate large amounts of telemetry data.
Service Defaults simplify OpenTelemetry integration, enabling:
Request tracing
Metrics collection
Dependency tracking
Performance monitoring
Because every service uses the same configuration, tracing requests across multiple services becomes much easier.
Service Discovery
Microservices often need to communicate with one another.
Instead of hardcoding service URLs, .NET Aspire supports service discovery.
For example, one service can communicate with another without needing to know its physical address.
This makes applications more flexible and easier to deploy across different environments.
HTTP Client Configuration
Many services communicate using HTTP.
Instead of configuring every HttpClient manually, Service Defaults apply shared settings such as:
Timeouts
Retry policies
Resilience handlers
Telemetry integration
This reduces repetitive code and ensures consistent behavior across services.
Customizing Service Defaults
Although Service Defaults provide sensible defaults, they are fully customizable.
You can add additional configurations such as:
This flexibility allows teams to tailor the shared configuration to their own requirements.
Practical Example
Imagine an e-commerce platform with several services:
Product Service
Order Service
Payment Service
Inventory Service
Notification Service
Without Service Defaults, each service would require individual configuration for logging, health checks, telemetry, and service discovery.
With Service Defaults, these configurations are defined once and automatically applied to every service, making the solution easier to manage and maintain.
Best Practices
When working with .NET Aspire Service Defaults, consider the following recommendations:
Keep shared configurations centralized.
Avoid adding business-specific logic to the Service Defaults project.
Use the same logging and telemetry configuration across all services.
Regularly review shared settings as your application evolves.
Test health endpoints before deploying to production.
Monitor telemetry to identify performance bottlenecks.
Document any custom configurations for your development team.
Following these practices helps maintain consistency across distributed applications.
Common Mistakes to Avoid
Developers new to .NET Aspire sometimes make configuration mistakes.
Avoid these common issues:
Duplicating shared configuration in individual services.
Placing business logic inside the Service Defaults project.
Ignoring health check endpoints.
Using different logging configurations across services.
Forgetting to update Service Defaults when introducing new shared requirements.
Keeping shared concerns centralized ensures your services remain consistent and easier to maintain.
Conclusion
.NET Aspire Service Defaults provide a simple yet powerful way to standardize configuration across cloud-native .NET applications. By centralizing logging, health checks, telemetry, service discovery, and other common infrastructure concerns, developers can reduce repetitive code and improve consistency throughout their solutions.
Whether you're building a small set of microservices or a large distributed system, Service Defaults help create applications that are easier to develop, maintain, monitor, and scale. Adopting this approach allows your team to spend less time configuring infrastructure and more time delivering valuable business features.