Skip to main content
The .NET Aspire app model is a code-first approach to defining and orchestrating your distributed application. At the heart of this model is the AppHost project, which uses the Aspire.Hosting library to describe your application’s resources and their relationships.

Understanding the AppHost

The AppHost is the orchestrator for your .NET Aspire application. It’s a console application that:
  • Defines all resources (projects, containers, databases, etc.)
  • Describes dependencies between resources
  • Configures service discovery
  • Manages the application lifecycle

Basic AppHost Structure

Every AppHost follows this basic structure:
Program.cs
var builder = DistributedApplication.CreateBuilder(args);

// Add resources here
var cache = builder.AddRedis("cache");
var api = builder.AddProject<Projects.Api>("api")
                 .WithReference(cache);

builder.Build().Run();
1
Create the builder
2
The DistributedApplication.CreateBuilder() method creates an instance of IDistributedApplicationBuilder, which provides the foundation for defining your application:
3
var builder = DistributedApplication.CreateBuilder(args);
4
Why pass args? The command-line arguments are essential for deployment tools to communicate with the AppHost. Always pass args from your Main method or top-level statements.
5
Add resources
6
Use extension methods on the builder to add resources to your application:
7
// Add a Redis container
var cache = builder.AddRedis("cache");

// Add a PostgreSQL server with a database
var db = builder.AddPostgres("postgres")
                .AddDatabase("catalogdb");

// Add a .NET project
var api = builder.AddProject<Projects.Api>("api");
8
Each Add* method returns an IResourceBuilder<T> that you can use to further configure the resource.
9
Build and run
10
Finally, build the application and start it:
11
builder.Build().Run();
12
This starts the Aspire dashboard and all defined resources.

Builder Configuration Options

You can customize the builder’s behavior using DistributedApplicationOptions:
var options = new DistributedApplicationOptions
{
    Args = args,
    DisableDashboard = false,
    AllowUnsecuredTransport = false,
    ContainerRegistryOverride = "myregistry.azurecr.io"
};

var builder = DistributedApplication.CreateBuilder(options);

Common Options

Disables the Aspire dashboard. Useful for headless scenarios or CI/CD environments.
var options = new DistributedApplicationOptions
{
    Args = args,
    DisableDashboard = true
};
Allows unsecured HTTP communication with the dashboard. Only use for development.
var options = new DistributedApplicationOptions
{
    Args = args,
    AllowUnsecuredTransport = true
};
Forces all container images to be pulled from a specific registry.
var options = new DistributedApplicationOptions
{
    Args = args,
    ContainerRegistryOverride = "myregistry.azurecr.io"
};

Accessing Services

The IDistributedApplicationBuilder exposes properties for customizing the application:
// Access configuration
var connectionString = builder.Configuration["MyService:ConnectionString"];

// Add configuration sources
builder.Configuration.AddJsonFile("appsettings.local.json", optional: true);

Execution Modes

The AppHost can run in different modes depending on how it’s invoked:

Run Mode

Normal execution mode where the AppHost starts all resources and the dashboard:
dotnet run
You can check the execution mode programmatically:
if (builder.ExecutionContext.IsRunMode)
{
    // Only execute in run mode
}

Publish Mode

Generates deployment manifests for publishing to cloud environments:
dotnet run --publisher manifest
Check for publish mode:
if (builder.ExecutionContext.IsPublishMode)
{
    // Only execute during manifest generation
}

Resource Lifecycle

The DistributedApplication implements the standard .NET IHost interface, which means it follows the host lifecycle:
var app = builder.Build();

// Option 1: Blocking call
app.Run();

// Option 2: Async with cancellation
await app.RunAsync(cancellationToken);

// Option 3: Start/Stop manually
await app.StartAsync();
// ... do work ...
await app.StopAsync();

Monitoring Resource State

You can monitor and react to resource state changes:
var app = builder.Build();

// Wait for a resource to be ready
await app.ResourceNotifications.WaitForResourceHealthyAsync("postgres");

// Monitor all resource state changes
await foreach (var update in app.ResourceNotifications.WatchAsync(cancellationToken))
{
    Console.WriteLine($"Resource {update.Resource.Name}: {update.Snapshot.State?.Text}");
}

AppHost Project Structure

A typical AppHost project has this structure:
MyApp.AppHost/
├── Program.cs              # Main application definition
├── MyApp.AppHost.csproj    # Project file
├── appsettings.json        # Optional configuration
└── .aspire/                # Local state (generated)

Project File Requirements

The AppHost project file must:
  1. Target net10.0 or later
  2. Set IsAspireHost to true
  3. Reference the Aspire.Hosting.AppHost package
MyApp.AppHost.csproj
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <IsAspireHost>true</IsAspireHost>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Aspire.Hosting.AppHost" Version="10.0.0" />
  </ItemGroup>

  <!-- Reference your projects -->
  <ItemGroup>
    <ProjectReference Include="..\MyApp.Api\MyApp.Api.csproj" />
  </ItemGroup>
</Project>

Next Steps

Now that you understand the basics of the AppHost, learn how to:

Define Resources

Learn about containers, projects, and executables

Wire Dependencies

Connect resources using WithReference

Manage Configuration

Configure your resources and services

Set Environment Variables

Pass configuration to your resources

Build docs developers (and LLMs) love