Infrastructure configuration often becomes difficult to maintain as an application grows. A small service may begin with a handful of deployment settings, but eventually the repository can contain Kubernetes manifests, environment-specific YAML files, Helm values, container configuration, secrets configuration, and CI/CD scripts.
.NET Aspire takes a different approach by allowing application infrastructure to be described in C# through the AppHost.
Aspire 13.5 extends this approach with improvements around deployment and infrastructure modeling, making it possible to describe more of the application's deployment topology from the AppHost rather than maintaining separate configuration for every environment.
The important question is not whether C# is universally better than YAML. It is whether keeping application resources and their relationships in one strongly typed model can reduce duplication, configuration drift, and deployment complexity.
What Is an Aspire AppHost?
The AppHost is the orchestration project in a .NET Aspire application.
A simplified application might look like this:
Aspire AppHost
|
+-- API
|
+-- PostgreSQL
|
+-- Redis
|
+-- Worker
The AppHost describes how these resources relate to each other.
For example:
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres")
.AddDatabase("appdb");
var cache = builder.AddRedis("cache");
builder.AddProject<Projects.Api>("api")
.WithReference(postgres)
.WithReference(cache);
builder.Build().Run();
The code expresses the application topology directly.
Instead of manually documenting that the API depends on PostgreSQL and Redis, those relationships are represented in the application model.
Why Replace Deployment YAML?
YAML itself is not the problem.
Kubernetes manifests, Helm charts, and other declarative configuration formats remain useful and widely adopted.
The problem appears when the same infrastructure relationship has to be represented in multiple places.
For example:
C# AppHost
|
+-- API
+-- Database
+-- Cache
Kubernetes YAML
|
+-- API
+-- Database
+-- Cache
Helm Values
|
+-- API
+-- Database
+-- Cache
CI/CD
|
+-- Environment
+-- Secrets
The more copies of the same infrastructure intent exist, the more opportunities there are for them to become inconsistent.
Infrastructure as Code in C#
The major benefit of an AppHost-based model is that infrastructure becomes part of a programming language with:
Types
Variables
Methods
Conditional logic
Reusable abstractions
IDE support
Compiler feedback
Consider:
var api = builder.AddProject<Projects.Api>("api");
var database = builder.AddPostgres("postgres")
.AddDatabase("orders");
api.WithReference(database);
The relationship is explicit.
A developer reading the code can immediately see that the API consumes the database.
Strong Typing vs Text Configuration
Compare the two approaches conceptually.
| Area | C# AppHost | YAML |
|---|---|---|
| Type checking | Strong | Limited |
| IDE support | Strong | Tool-dependent |
| Refactoring | Strong | More manual |
| Reusable logic | Natural | Usually templates/anchors/tools |
| Syntax errors | Compiler feedback | Parser feedback |
| Application relationship modeling | Direct | Indirect |
| Kubernetes ecosystem | Requires generated/deployment integration | Native |
| Familiarity | .NET developers | Broad DevOps familiarity |
Neither approach is universally superior.
The choice depends on the team and the infrastructure being managed.
AppHost as an Application Topology
One of the strongest concepts in Aspire is that the AppHost can represent application topology rather than merely deployment settings.
For example:
AppHost
|
+------------+------------+
| | |
v v v
API Worker Gateway
| |
v v
PostgreSQL Queue
|
v
Storage
The graph communicates dependencies.
This becomes useful when the application contains multiple services.
Environment-Specific Configuration
Real applications rarely have identical infrastructure in every environment.
For example:
Development
|
+-- Local PostgreSQL
+-- Local Redis
Staging
|
+-- Managed PostgreSQL
+-- Managed Redis
Production
|
+-- Managed PostgreSQL
+-- Managed Redis
The infrastructure model should make those differences explicit.
However, environment-specific branching should be used carefully.
Avoid turning the AppHost into a large collection of nested conditions:
if (environment == "production")
{
// 500 lines of infrastructure
}
else if (environment == "staging")
{
// another 500 lines
}
When the differences become substantial, reusable infrastructure components and separate deployment policies may be easier to maintain.
Deployment YAML Still Has a Role
Replacing YAML should not become a goal by itself.
There are cases where Kubernetes YAML remains appropriate.
For example:
Platform-level Kubernetes configuration
Cluster administration
Specialized Kubernetes resources
Infrastructure owned by a platform team
Existing GitOps workflows
Organizations standardized around Helm or Kustomize
Aspire should therefore complement existing infrastructure practices where necessary rather than forcing every deployment concern into C#.
The Hybrid Approach
A practical architecture can use both.
Aspire AppHost
|
+-- Application Resources
+-- Service Relationships
+-- Environment Configuration
|
v
Deployment / Infrastructure Layer
|
+-- Kubernetes
+-- Azure
+-- CI/CD
+-- Platform Policies
This keeps application topology close to the application while leaving platform-level concerns to the platform layer.
Resource Relationships
One of the biggest benefits of AppHost-based infrastructure is explicit resource relationships.
For example:
var database = builder.AddPostgres("postgres")
.AddDatabase("orders");
builder.AddProject<Projects.OrderApi>("orders-api")
.WithReference(database);
The API has an explicit dependency on the database.
This is more useful than simply storing a connection string because the infrastructure model understands that the database is a resource.
The application configuration can then be generated or supplied according to the deployment environment.
Avoid Hard-Coded Infrastructure Values
Even in a C# infrastructure model, avoid scattering environment-specific values throughout the code.
Instead of:
var endpoint =
"https://production-storage.example.com";
prefer configuration or resource references.
This keeps the infrastructure model portable.
Reusable Infrastructure Components
As an application grows, repeated infrastructure patterns can be extracted into methods.
For example:
static IResourceBuilder<IResourceWithConnectionString>
AddApplicationDatabase(
IDistributedApplicationBuilder builder)
{
return builder.AddPostgres("postgres")
.AddDatabase("appdb");
}
The exact generic types depend on the resources being modeled, but the design principle is important.
Repeated infrastructure should have one definition where practical.
This reduces copy-and-paste configuration.
Infrastructure Validation
C# provides an additional advantage because infrastructure code can be tested.
For example, a test can verify that a resource exists or that expected relationships are represented.
The exact testing strategy depends on how the AppHost is structured, but the principle is useful:
Infrastructure Model
|
v
Validation
|
+-- Required Resource?
+-- Dependency Present?
+-- Configuration Valid?
+-- Environment Rules?
This moves some infrastructure errors earlier in the development process.
CI/CD Integration
A C# AppHost does not eliminate CI/CD.
The pipeline still needs to:
Restore dependencies.
Build the application.
Validate the AppHost.
Produce deployment artifacts.
Apply infrastructure.
Deploy application services.
Run post-deployment validation.
A simplified pipeline might look like:
Commit
|
v
Build
|
v
Test
|
v
AppHost Validation
|
v
Deployment Artifact
|
v
Environment
|
v
Smoke Tests
The important improvement is that application infrastructure intent is represented closer to the application source.
Common Mistakes
Trying to Eliminate YAML Everywhere
Not every YAML file is application infrastructure.
CI/CD pipelines and platform tooling may still use YAML for good reasons.
Putting Secrets in the AppHost
Infrastructure code is still source code.
Do not hard-code credentials or secrets.
Overusing Conditional Logic
Too many environment-specific branches can make the AppHost difficult to understand.
Ignoring Platform Ownership
A platform team may own cluster-level configuration.
Application teams should not necessarily duplicate or replace those controls.
Assuming C# Automatically Means Better Infrastructure
The language is not the deciding factor.
Good infrastructure design depends on clear ownership, repeatability, security, observability, and operational practices.
Troubleshooting
Deployment Works Locally but Fails in the Target Environment
Compare the generated deployment configuration and environment-specific settings.
Check:
Resource availability
Identity permissions
Network configuration
Secrets
Storage
Container configuration
Resource Dependency Is Missing
Inspect the AppHost relationship.
For example:
api.WithReference(database);
Without an explicit relationship, the application may not receive the expected resource configuration.
Configuration Differs Between Environments
Identify which values are environment-specific and move them into the appropriate configuration or deployment layer rather than duplicating entire resource definitions.
Best Practices
Use the AppHost to describe application topology.
Keep resource relationships explicit.
Avoid duplicating infrastructure definitions.
Keep secrets outside source code.
Reuse common infrastructure patterns.
Keep environment-specific differences deliberate.
Use YAML where Kubernetes-native or platform-level configuration requires it.
Validate infrastructure changes in CI.
Keep platform and application ownership separate.
Treat deployment artifacts as part of the application's release process.
Avoid unnecessary environment-specific branching.
Document exceptional infrastructure behavior.
Advantages and Disadvantages
Advantages
Infrastructure relationships are represented in C#.
.NET developers can use familiar language and tooling.
Resource dependencies become easier to understand.
Reusable infrastructure patterns are straightforward to create.
Compiler feedback can catch some classes of configuration problems.
Application topology can live close to application code.
Disadvantages
Teams already invested heavily in Kubernetes tooling may not want another abstraction.
Platform-specific configuration may still require YAML or other formats.
Poorly designed AppHosts can become difficult to maintain.
Infrastructure code still requires operational expertise.
Cross-environment configuration can become complex if not structured carefully.
When Should You Use AppHost Infrastructure?
AppHost-based infrastructure is particularly attractive when:
The application is primarily .NET.
Developers own both application and local orchestration.
Multiple services have clear dependencies.
Local development should resemble deployment topology.
The team wants infrastructure relationships represented in code.
Traditional Kubernetes configuration may remain preferable when:
The platform team owns deployment definitions.
The organization uses GitOps extensively.
Kubernetes resources are highly specialized.
Infrastructure is shared across many unrelated applications.
The right answer can also be a combination of both approaches.
Conclusion
.NET Aspire's AppHost provides a way to describe application infrastructure and resource relationships using C#. That can reduce duplication between application code and deployment configuration, particularly for .NET teams building distributed applications.
But replacing deployment YAML should not be treated as the objective. The real objective is to create a reliable infrastructure model with clear ownership, repeatable deployment, secure configuration, and minimal drift.
For many .NET applications, the most practical approach is a hybrid one: use Aspire to describe application topology and resource relationships while retaining Kubernetes, cloud-platform, and CI/CD tooling where those layers provide capabilities the AppHost should not own.
The strongest infrastructure model is not the one with the least YAML. It is the one where developers and operators can clearly understand what the application needs, how its resources are connected, and which layer is responsible for deploying and securing each part.

Join the conversation! Your thoughts help the community grow.