Introduction
Remember the last time you tried to run a distributed app locally? You probably spent half your day writing docker-compose files, fighting with connection strings, and trying to figure out why service A couldn't talk to service B. Then when everything finally worked on your machine, you crossed your fingers hoping it would work the same way in production.
.NET Aspire changes all of that.
Released in May 2024 at Microsoft Build, .NET Aspire is Microsoft's answer to the complexity of building cloud-native distributed applications. It's not just another framework or another thing to learn. It's a complete rethinking of how we build, run, and debug distributed apps in the .NET ecosystem.
In this guide, I'll walk you through everything you need to know about .NET Aspire. Whether you're building microservices, working with containers, or just trying to get your web app to talk to a database without pulling your hair out, this article has you covered.
What Is .NET Aspire Anyway?
At its core, .NET Aspire is a local development orchestration toolchain. That's a fancy way of saying it helps you run and connect all the pieces of your distributed application without making you write a ton of configuration files.
Think of it this way: you have a web app, an API, a database, maybe Redis for caching, and a message queue. Normally, you'd need to:
Write connection strings for everything
Set up service discovery so things can find each other
Configure logging and monitoring
Write docker-compose files
Set up health checks
Configure retry policies
Deal with startup order dependencies
With .NET Aspire, you write a few lines of C# code and hit F5. Everything starts up, connects properly, and you get a nice dashboard showing you what's happening. No YAML files. No configuration hell.
The Three Pillars of .NET Aspire
.NET Aspire is built on three main concepts:
1. Orchestration (The AppHost)
The AppHost is the heart of your Aspire application. It's a special .NET project that defines what your application is made of and how everything connects together.
Here's a simple example:
csharp
var builder = DistributedApplication.CreateBuilder(args);
// Add a PostgreSQL database
var postgres = builder.AddPostgres("postgres")
.AddDatabase("mydb");
// Add a Redis cache
var cache = builder.AddRedis("cache");
// Add your API and connect it to the database and cache
var api = builder.AddProject<Projects.MyApi>("api")
.WithReference(postgres)
.WithReference(cache);
// Add your web frontend and connect it to the API
builder.AddProject<Projects.MyWeb>("frontend")
.WithReference(api);
builder.Build().Run();
That's it. When you run this, Aspire will:
Start PostgreSQL in a container
Start Redis in a container
Launch your API project
Launch your web frontend
Configure all the connection strings automatically
Set up service discovery so everything can find each other
Give you a dashboard to see it all running
2. Components (The Building Blocks)
Components are NuGet packages that connect your app to popular services and platforms. They're like Lego blocks for cloud-native apps.
Aspire has components for:
Databases
PostgreSQL
SQL Server
MySQL
MongoDB
Oracle
Azure Cosmos DB
Caching
Redis
Valkey
Messaging
RabbitMQ
Azure Service Bus
Apache Kafka
NATS
Storage
Azure Blob Storage
Azure Queue Storage
AWS S3
And many more...
Each component handles all the boring stuff automatically:
Connection configuration
Health checks
Logging and telemetry
Retry policies
Timeouts
3. Tooling (The Developer Experience)
Aspire comes with project templates and great IDE support for Visual Studio, VS Code, and the .NET CLI. When you create an Aspire project, you get:
AppHost: The orchestration project
ServiceDefaults: Shared configuration for telemetry, health checks, and service discovery
Your actual projects: The API, web app, workers, etc.
Everything is set up and ready to go.
Why Should You Care About .NET Aspire?
Let me be honest. There are already tools out there for this stuff. Docker Compose works. Kubernetes works. So why learn another thing?
Here's why Aspire is worth your time:
It Saves You Time
With Docker Compose, you write YAML. With Aspire, you write C# code. Which means:
You get IntelliSense and autocomplete
Compile-time type checking catches errors
Refactoring tools work
You can debug your infrastructure code
It's Made for .NET Developers
Docker Compose is language-agnostic, which is great if you're using multiple languages. But if you're a .NET shop, Aspire speaks your language. It integrates with your existing .NET projects seamlessly.
The F5 Experience Just Works
Clone the repo. Open the solution. Hit F5. Everything starts up. That's the promise, and Aspire actually delivers on it.
No more "works on my machine" problems where new team members spend a day getting the dev environment working.
The Dashboard Is Really Good
When you run an Aspire app, you get a dashboard that shows:
All your services and their health status
Logs from everything in one place
Distributed traces showing requests flowing through your system
Metrics and performance data
Environment variables each service is using
It's like having a mini Azure Portal for your local development.
It Handles the Production Stuff
Health checks, telemetry, retry policies, timeouts - all the things you need in production but often skip in development. Aspire builds them in from day one.
Getting Started with .NET Aspire
Let's build something. I'll show you how to create a simple application with a web frontend, an API, and a database.
Prerequisites
You need:
.NET 9 SDK (or .NET 8 works too)
Docker or Podman (for running containers)
Visual Studio 2022, VS Code, or just the .NET CLI
Install the Aspire Workload
Open a terminal and run:
bash
dotnet workload install aspire
This installs the Aspire templates and tools.
Create Your First Aspire App
bash
dotnet new aspire-starter -n MyFirstAspireApp
cd MyFirstAspireApp
This creates a solution with four projects:
MyFirstAspireApp.Web: A Blazor web frontend
MyFirstAspireApp.ApiService: A minimal API backend
MyFirstAspireApp.AppHost: The orchestration project
MyFirstAspireApp.ServiceDefaults: Shared configuration
Run It
bash
cd MyFirstAspireApp.AppHost
dotnet run
You'll see output like this:
info: Aspire.Hosting.DistributedApplication[0]
Aspire version: 9.0.0
info: Aspire.Hosting.DistributedApplication[0]
Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
Login to the dashboard at https://localhost:17299/login?t=abc123...
Click that link and you'll see the Aspire Dashboard with your services running.
Look at the AppHost Code
Open MyFirstAspireApp.AppHost/Program.cs:
csharp
var builder = DistributedApplication.CreateBuilder(args);
var apiService = builder.AddProject<Projects.MyFirstAspireApp_ApiService>("apiservice");
builder.AddProject<Projects.MyFirstAspireApp_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(apiService);
builder.Build().Run();
Super simple. The web frontend references the API service, so Aspire automatically configures service discovery. The web app can call the API without hardcoding URLs.
Adding a Database
Let's make this more realistic by adding PostgreSQL.
Install the PostgreSQL Component
In the AppHost project:
bash
dotnet add package Aspire.Hosting.PostgreSQL
Update the AppHost
csharp
var builder = DistributedApplication.CreateBuilder(args);
// Add PostgreSQL
var postgres = builder.AddPostgres("postgres")
.WithPgAdmin() // Optional: adds pgAdmin UI
.AddDatabase("mydb");
// Connect the API to the database
var apiService = builder.AddProject<Projects.MyFirstAspireApp_ApiService>("apiservice")
.WithReference(postgres);
builder.AddProject<Projects.MyFirstAspireApp_Web>("webfrontend")
.WithExternalHttpEndpoints()
.WithReference(apiService);
builder.Build().Run();
Use the Database in Your API
In the API project, install the client component:
bash
dotnet add package Aspire.Npgsql.EntityFrameworkCore.PostgreSQL
In Program.cs:
csharp
var builder = WebApplication.CreateBuilder(args);
// Add Aspire service defaults (health checks, telemetry)
builder.AddServiceDefaults();
// Add PostgreSQL with EF Core
builder.AddNpgsqlDbContext<MyDbContext>("mydb");
var app = builder.Build();
app.MapGet("/products", async (MyDbContext db) =>
{
return await db.Products.ToListAsync();
});
app.Run();
That's it. No connection strings. No configuration. Aspire handles it all.
When you run the app now, Aspire will:
Pull the PostgreSQL container image if needed
Start PostgreSQL
Wait for it to be healthy
Pass the connection string to your API
Start your API
Start your web frontend
All automatically.
Real-World Example: E-Commerce Microservices
Let me show you a more realistic scenario. Let's say you're building an e-commerce system with:
Product catalog API
Shopping cart API
Order processing worker
PostgreSQL for products
Redis for caching and cart data
RabbitMQ for messaging
Here's how you'd set that up:
csharp
var builder = DistributedApplication.CreateBuilder(args);
// Infrastructure
var postgres = builder.AddPostgres("postgres")
.AddDatabase("catalogdb");
var redis = builder.AddRedis("redis");
var rabbitmq = builder.AddRabbitMQ("messaging");
// Services
var catalogApi = builder.AddProject<Projects.CatalogApi>("catalog-api")
.WithReference(postgres)
.WithReference(redis);
var cartApi = builder.AddProject<Projects.CartApi>("cart-api")
.WithReference(redis)
.WithReference(rabbitmq);
var orderWorker = builder.AddProject<Projects.OrderProcessor>("order-worker")
.WithReference(rabbitmq)
.WithReference(postgres);
// Frontend
builder.AddProject<Projects.WebApp>("web")
.WithReference(catalogApi)
.WithReference(cartApi);
builder.Build().Run();
Run this, and you've got a complete microservices system running locally with all the connections figured out. No docker-compose.yml with 200 lines of configuration.
The Aspire Dashboard Deep Dive
The dashboard is one of Aspire's killer features. Let me walk you through it.
Resources View
Shows all your services, containers, and executables. For each one you see:
Current state (Running, Stopped, Failed)
Endpoints (click to open in browser)
Environment variables
Start time and restart count
Console Logs
Real-time logs from all your services in one place. You can:
Filter by service
Search for specific text
See structured logs in a nice table format
Expand log entries to see full details
Structured Logs
This is where logs really shine. Instead of plain text, you get structured data you can query and filter:
Filter by log level (Info, Warning, Error)
Filter by service
Search across all fields
See the full context of each log entry
Traces
This is amazing for debugging. You can see the complete path of a request through your system:
User hits the web app
Web app calls catalog API
Catalog API queries database
Catalog API checks Redis cache
Response goes back to user
Each step shows timing, so you can see where slowness happens.
Metrics
Performance metrics for your services:
Request rates
Response times
Error rates
Custom metrics you add
Aspire Components in Detail
Let's look at how components actually work. I'll use Redis as an example.
Hosting Integration (in AppHost)
csharp
// This adds Redis as a resource in your app model
var redis = builder.AddRedis("cache");
// You can customize it
var redis = builder.AddRedis("cache")
.WithRedisCommander() // Adds a web UI
.WithDataVolume(); // Persists data
Client Integration (in your services)
csharp
// In your API project
builder.AddRedisClient("cache");
// Now you can inject IConnectionMultiplexer
app.MapGet("/", (IConnectionMultiplexer redis) =>
{
var db = redis.GetDatabase();
db.StringSet("greeting", "Hello from Redis!");
return db.StringGet("greeting");
});
The client integration automatically adds:
Connection configuration
Health checks
Logging and telemetry
Connection pooling
Retry policies
You don't write any of that. It's just there.
Aspire vs. Docker Compose
People ask this a lot. Here's my take.
Docker Compose Is Better When...
You're using multiple languages (Java, Python, Node.js, .NET)
You need very specific container configurations
Your team is already fluent in Docker Compose
You're not primarily a .NET shop
.NET Aspire Is Better When...
You're building .NET applications
You want type safety in your infrastructure code
You want to debug your orchestration setup
You want integrated telemetry and health checks out of the box
You want service discovery without extra setup
You value the F5 developer experience
Can You Use Both?
Yes! Aspire can generate Docker Compose files from your AppHost. There are also community tools like Aspirate that can convert Aspire apps to Kubernetes manifests.
So you can use Aspire for local dev and still deploy with Docker Compose or Kubernetes in production.
Aspire vs. Dapr
This is another common question. They actually complement each other.
Dapr is a runtime that runs alongside your application (as a sidecar) and provides APIs for:
Service-to-service calls
State management
Pub/sub messaging
Bindings
Secrets management
Configuration
Aspire is a local development tool that orchestrates your services and provides observability.
You can use them together! Aspire even has a Dapr integration. You get Aspire's great local dev experience plus Dapr's production-grade distributed application patterns.
csharp
// Using Aspire with Dapr
var builder = DistributedApplication.CreateBuilder(args);
var stateStore = builder.AddDaprStateStore("statestore");
var pubSub = builder.AddDaprPubSub("pubsub");
var api = builder.AddProject<Projects.MyApi>("api")
.WithDaprSidecar(new DaprSidecarOptions
{
AppId = "myapi",
EnableApiLogging = true
})
.WithReference(stateStore)
.WithReference(pubSub);
Deploying Aspire Apps
Aspire is focused on local development, but it also helps with deployment.
Azure Deployment
The easiest path is Azure Container Apps. From Visual Studio, you can right-click publish. Or use the Azure Developer CLI:
bash
azd init
azd up
This will:
Containerize your applications
Provision Azure resources (Container Apps, databases, Redis, etc.)
Deploy everything
Wire up all the connections
Kubernetes Deployment
Aspire generates a manifest file that describes your application. Community tools can convert this to Kubernetes YAML:
bash
# Using Aspirate (community tool)
dotnet tool install -g aspirate
aspirate generate
This creates Kubernetes manifests you can deploy with kubectl or Helm.
Other Platforms
The manifest format is extensible. The community is building plugins for AWS, Google Cloud, and other platforms.
Adding Aspire to Existing Apps
You don't have to start from scratch. You can add Aspire to existing .NET applications.
Step 1: Add the AppHost Project
bash
dotnet new aspire-apphost -n MyApp.AppHost
dotnet sln add MyApp.AppHost
Step 2: Reference Your Existing Projects
In the AppHost:
csharp
var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddProject<Projects.MyExistingApi>("api");
builder.AddProject<Projects.MyExistingWeb>("web")
.WithReference(api);
builder.Build().Run();
Step 3: Add ServiceDefaults (Optional but Recommended)
Create a ServiceDefaults project:
bash
dotnet new aspire-servicedefaults -n MyApp.ServiceDefaults
In your existing projects, add a reference and call:
csharp
builder.AddServiceDefaults();
This adds health checks, telemetry, and service discovery support.
That's it. You're using Aspire now.
Community and Ecosystem
Aspire has a growing community building cool stuff:
Community Toolkit
The Aspire Community Toolkit has components for:
Golang apps
Java apps
Node.js extensions
Python extensions
Ollama (for running LLMs locally)
Meilisearch
Dapr
SQLite
And many more...
Third-Party Integrations
AWS: Aspire.Hosting.AWS for CloudFormation and AWS services
Grafana + Prometheus: For advanced metrics
Seq: For structured logging
Tools
Aspirate: Converts Aspire apps to Kubernetes manifests
Aspir8: Another tool for Kubernetes deployment
Best Practices
Here are some tips I've learned using Aspire:
Keep Your AppHost Simple
The AppHost should just wire things together. Don't put business logic there.
Use ServiceDefaults
Even if you don't think you need it, add ServiceDefaults to your projects. The health checks and telemetry are worth it.
Name Things Clearly
Use descriptive names for your resources:
csharp
// Good
var productDb = builder.AddPostgres("postgres").AddDatabase("products");
// Not so good
var db1 = builder.AddPostgres("pg").AddDatabase("db");
Use WithReference for Dependencies
Always use WithReference to connect services. Don't try to manually configure service URLs.
csharp
// Good
var api = builder.AddProject<Projects.Api>("api");
builder.AddProject<Projects.Web>("web")
.WithReference(api);
// Bad
builder.AddProject<Projects.Web>("web")
.WithEnvironment("API_URL", "http://localhost:5000");
Start with the Starter Template
When learning, use dotnet new aspire-starter. It shows you the patterns.
Use Volumes for Data You Want to Keep
csharp
var postgres = builder.AddPostgres("postgres")
.WithDataVolume(); // Data persists between runs
Without this, your data disappears when you stop the app.
Common Issues and Solutions
"Can't connect to Docker"
Make sure Docker Desktop or Podman is running. Aspire needs a container runtime.
"Connection string is wrong"
Let Aspire generate connection strings. Don't try to override them unless you really need to.
"Service discovery isn't working"
Make sure you're using WithReference in the AppHost and calling builder.AddServiceDefaults() in your projects.
"Dashboard won't load"
Check the console output for the dashboard URL. Sometimes the port changes. The URL includes a login token.
What's Next for Aspire?
Microsoft is actively developing Aspire. Some things coming:
More cloud provider integrations
Better support for existing apps
More components
Enhanced deployment tools
Improved debugging experience
Should You Use .NET Aspire?
Here's how I think about it:
Use Aspire if:
You're building .NET cloud-native applications
You work with distributed systems or microservices
You're tired of configuration hell
You want better local development experience
You value observability and debugging
Maybe skip Aspire if:
You're building a simple single-project app
Your team doesn't use .NET
You're already happy with your Docker Compose setup and don't want to change
Worth noting:
Aspire is still young. It went 1.0 in May 2024. There will be rough edges. But Microsoft is investing heavily in it, and the community is growing fast.
Wrapping Up
.NET Aspire solves real problems. If you've ever spent hours debugging why your API can't connect to your database in development, or if you've onboarded a new developer and watched them struggle for a day to get everything running, you know the pain Aspire addresses.
It's not perfect. It's opinionated. It's .NET-focused. But for .NET developers building cloud-native apps, it's a game-changer.
The best way to learn is to try it. Create an Aspire app. Add a database. Add Redis. Watch how it all just works. Then think about how you'd do the same thing with docker-compose or manual configuration.
I think you'll be impressed.
Where to Learn More
Official Resources
Aspire Documentation - Complete reference
.NET Aspire Samples - Example applications
Aspire GitHub - Source code and issues
.NET Blog - Latest updates and announcements
Video Content
Microsoft's .NET YouTube channel has Aspire tutorials
.NET Conf sessions on Aspire
Community members posting walkthroughs
Community
Reddit: r/dotnet - Active discussions about Aspire
Stack Overflow: Tag your questions with
dotnet-aspireDiscord: .NET Discord server has an Aspire channel
Twitter/X: Follow @dotnet and #dotnetaspire
Where People Are Asking Questions
Stack Overflow
Search for questions tagged with dotnet-aspire. Common topics:
How to add X service to Aspire
Deployment questions
Integration with existing apps
Troubleshooting connection issues
GitHub Discussions
The dotnet/aspire repo has active discussions on:
Feature requests
Architecture questions
Best practices
Community integrations
Reddit r/dotnet
People are posting about:
Getting started guides
Comparisons with other tools
Real-world use cases
Migration experiences
Microsoft Q&A
The .NET section has lots of Aspire questions, especially from people just getting started.
Contribute
Aspire is open source. If you build a useful component or integration, consider contributing it to the Community Toolkit. The ecosystem is growing fast.
About Me: I'm a .NET developer who loves working with cloud-native applications and microservices.
Found this guide helpful? Share it with your team. What are you planning to build with Aspire?