.NET Aspire: A First Look

.NET Aspire: A First Look

Markus Lehmann ยท June 10, 2025
.NET AspireDistributed SystemsCloud Native
.NETTutorials

Microsoft's .NET Aspire has been getting a lot of attention, and after spending a few weeks integrating it into a real project, I can see why. Aspire fundamentally changes how you develop, test, and deploy distributed .NET applications. Here's my take on what it brings to the table.

What Problem Does Aspire Solve?

Building distributed applications involves a lot of ceremony. You need databases, caches, message queues, and multiple services that all need to discover and communicate with each other. Locally, you end up with Docker Compose files, environment variable scripts, and a README with fifteen setup steps that nobody follows.

Aspire replaces all of that with a single orchestration project that defines your entire application topology in C# code.

The AppHost Pattern

The core of Aspire is the AppHost project. This is where you declare all the resources your application needs:

var builder = DistributedApplication.CreateBuilder(args);

var sql = builder.AddSqlServer("sql")
    .AddDatabase("appdb");

var redis = builder.AddRedis("cache");

var api = builder.AddProject<Projects.MyApp_Api>("api")
    .WithReference(sql)
    .WithReference(redis);

builder.AddProject<Projects.MyApp_Web>("web")
    .WithReference(api);

builder.Build().Run();

This code does more than it looks like. It spins up SQL Server and Redis containers, configures connection strings, sets up service discovery between projects, and provides a dashboard to monitor everything. All from a single dotnet run command.

Service Discovery

One of the most valuable features is automatic service discovery. When you add .WithReference(api) to the web project, Aspire configures the necessary environment variables so the web project can find the API using a logical name:

var client = httpClientFactory.CreateClient();
var response = await client.GetAsync("https+http://api/weatherforecast");

No hardcoded URLs, no port management, no configuration files. The service discovery layer resolves the logical name to the actual endpoint at runtime. In production, this maps to your cloud provider's service discovery mechanism.

The Developer Dashboard

Aspire ships with a built-in dashboard that provides observability into your running application. It shows:

  • Resources: Status of all services, containers, and executables
  • Console logs: Aggregated output from all services in one place
  • Structured logs: Searchable, filterable structured log entries
  • Traces: Distributed traces across service boundaries using OpenTelemetry
  • Metrics: Real-time performance metrics

This dashboard alone saves a significant amount of time during development. Instead of tailing multiple terminal windows, everything is centralized and searchable.

Built-in Integrations

Aspire provides integrations for common infrastructure components. Each integration handles health checks, telemetry, and configuration automatically:

// In your service's Program.cs
builder.AddSqlServerDbContext<AppDbContext>("appdb");
builder.AddRedisDistributedCache("cache");

These one-liners replace dozens of lines of manual configuration. The SQL Server integration sets up the connection string, configures health checks, and adds OpenTelemetry instrumentation for database calls.

What I Like

Local development experience. Starting the entire application stack with one command is a game-changer. No more maintaining Docker Compose files in parallel with your application code.

Consistent observability. Every service automatically gets structured logging, distributed tracing, and health checks through the ServiceDefaults pattern.

Azure deployment story. Running azd up deploys the entire topology to Azure Container Apps with appropriate infrastructure provisioned automatically via Bicep.

What Could Be Better

Learning curve for the abstractions. Understanding how the AppHost orchestration maps to actual infrastructure takes time. The magic is helpful until you need to customize something specific.

Container startup times. With multiple containers starting simultaneously, the initial startup can be slow. The WaitFor and WaitForCompletion methods help sequence dependencies, but you need to be deliberate about using them.

Limited non-Azure support. While the local development experience is cloud-agnostic, the deployment story heavily favors Azure. AWS and GCP support is growing but not yet on par.

Verdict

.NET Aspire is a significant step forward for building distributed .NET applications. It removes a category of infrastructure concerns from day-to-day development and provides excellent observability out of the box. If you're building multi-service .NET applications, especially targeting Azure, Aspire is worth investing the time to learn. It has already become a standard part of my project templates.


Comments (3)

Hannah Feb 26, 2026 · 17:08

I have a question: does this also apply to older versions?

Clara Mar 13, 2026 · 20:08

Interesting thought, thanks for adding that.

David Mar 07, 2026 · 23:08

Exactly! I had the same thought.

Anna Feb 27, 2026 · 17:08

Thanks for sharing — very helpful.

Ben Feb 28, 2026 · 17:08

Could you elaborate on this topic in a follow-up post?


Leave a comment

An unhandled error has occurred. Reload ๐Ÿ—™

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.