Each arrow = configuration + credentials + setup time + potential failure
We've Tried to Fix This Before...
Docker Compose
โ Defines dependencies
โ Somewhat portable
โ Version drift
โ Init scripts are fragile
โ No IDE integration
โ Debugging is painful
Shared Dev Environment
โ One setup to rule them all
โ "Real" data
โ Developers collision
โ Can't test breaking changes
โ Remote debugging
โ "Who broke dev?!"
The Developer's Dream
git clone โ F5
That's it. That's the dream.
And for product owners:
New developer productive in hours, not weeks
Enter .NET Aspire
What it actually does (and doesn't do)
What is .NET Aspire?
A local orchestrator for distributed .NET apps
โ What It Is
Development orchestrator
Service discovery
Resource lifecycle management
Built-in observability
Integration test framework
โ What It's NOT
Production orchestrator
Kubernetes replacement
Cloud deployment solution
Container platform
Magic pixie dust
The F5 Experienceโข
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("db")
.WithDataVolume(); // Data survives restarts!
var app = builder.AddProject<Projects.MyApp>("app")
.WithReference(postgres)
.WithReplicas(3); // Run 3 instances
builder.Build().Run();
Defines your app model Service dependencies Resource configuration
๐ฎ DCP
Orchestrates resources Manages lifecycle Service discovery
๐ Dashboard
Logs & traces Resource status Environment vars
๐ง Integrations
PostgreSQL, Redis RabbitMQ, Kafka Azure services
All accessible with one F5 press
Demo Time
Let's see it in action with DrawTogether.NET
Demo: DrawTogether.NET
Real-world collaborative drawing application
SQL Server with EF Core migrations
Multiple service instances (clustering)
Akka.NET actor system
Persistent data volumes
What we'll see:
F5 to launch everything
Dashboard tour
Multiple instances running
Distributed debugging
What Just Happened?
Automatically Started:
SQL Server container
Created database
Ran EF migrations
Started 3 app instances
Configured service discovery
Set up observability
You Did:
Pressed F5
Time from git clone to running app: < 2 minutes
Going Deeper
Real code, real patterns
Real-World AppHost
var sqlServer = builder.AddSqlServer("sql", saPassword)
.WithDataVolume(); // Persistent across restarts
var db = sqlServer.AddDatabase("DrawTogetherDb");
// Run migrations before app starts
var migrationService = builder
.AddProject<Projects.MigrationService>("migrations")
.WaitFor(db)
.WithReference(db);
// Start app only after migrations complete
var app = builder.AddProject<Projects.DrawTogether>("app")
.WithReplicas(3)
.WithReference(db)
.WaitForCompletion(migrationService);
Migration Service Pattern
Migration Service
// MigrationService/Program.cs
var context = services
.GetRequiredService<AppDbContext>();
await context.Database
.MigrateAsync();
await SeedData(context);
// Signal completion
app.Run();
Benefits
Migrations run once
Before app starts
Can seed data
Version controlled
Works with teams
โ ๏ธ Avoiding Vendor Lock-in
โ Don't: Aspire Client Packages in Your App
// In your app's Program.cs - AVOID THIS!
builder.AddServiceDefaults();
builder.AddSqlServerDbContext<AppContext>("sqldata");
builder.AddRedisCache("cache");
// Magic service discovery & config
// Tightly coupled to Aspire runtime
// How do you deploy without Aspire?
โ Do: Standard .NET Configuration
// In AppHost - this is fine!
var redis = builder.AddRedis("cache");
app.WithEnvironment("RedisConnection",
redis.GetConnectionString());
// In your app's Program.cs - standard .NET
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = config["RedisConnection"];
});
Automatic OpenTelemetry Integration
Structured Logs
Distributed Traces
System & App Metrics
Zero Configuration
Just works out of the box
Integration Testing Revolution
Real dependencies, no mocks
Real DrawTogether.NET Test Fixture
[Test]
public async Task CanCreateGameSessionAndDraw()
{
// Start DrawTogether with real SQL Server
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<DrawTogether_AppHost>();
await using var app = await appHost.BuildAsync();
await app.StartAsync();
// Wait for SQL migrations to complete
await app.WaitForResource("sqlserver")
.WaitForHealthy();
// Connect with real SignalR client
var blazorApp = app.CreateHttpClient("drawtogether");
var hubConnection = new HubConnectionBuilder()
.WithUrl($"{blazorApp.BaseAddress}draw-hub")
.Build();
await hubConnection.StartAsync();
// Real drawing operations, real database persistence
await hubConnection.InvokeAsync("CreateSession", "TestRoom");
await hubConnection.InvokeAsync("DrawLine", 10, 10, 50, 50);
// Verify in real SQL database
var dbContext = app.Services.GetRequiredService<GameDbContext>();
var session = await dbContext.Sessions
.FirstOrDefaultAsync(s => s.Name == "TestRoom");
Assert.That(session, Is.Not.Null);
}
Demo: Integration Testing
Aspire.Hosting.Testing in Action
Real DrawTogether integration tests
Full application spin-up per test
Parallel test execution
Automatic cleanup
Key Benefits:
No shared test database
No test data pollution
True end-to-end testing
Catches real integration issues
Reality Check
Let's talk about what doesn't work
What Aspire ISN'T (Yet)
The Dream ๐
Development โ
Testing โ
Staging ๐ค
Production ๐
The Reality ๐ฌ
Dev-only orchestrator
No production story
Limited cloud support
Manual deployment config
"The deployment story is... virtually non-existent"
The Deployment "Story" ๐
Target
Status
Reality
Azure (azd)
โ Works
Good integration, Container Apps
Kubernetes
โ ๏ธ Community
Aspirate/Aspire8 - not production ready
Docker Compose
๐ง Manual
Generated, but needs manual config
AWS/GCP
โ DIY
No tooling, no roadmap
Bottom line: Great for dev, figure out prod yourself
Demo: Let's Try Deployment Anyway
Using the Aspire CLI
# Generate deployment artifacts
aspire generate --output-format docker-compose
# What we get vs what we need
Spoiler Alert:
Generates basic structure โ
Missing environment configs โ
No secrets management โ
Networking needs work โ
Practical Adoption
How to actually use this today
Can You Use .NET Aspire?
Prerequisites for Success:
1. Can you run dependencies locally?
Seeded databases (SQL, PostgreSQL, MongoDB)
Redis, RabbitMQ, storage emulators
Organizational commitment to maintain seed data
2. Is your code accessible?
Monorepo โ Perfect fit
Multiple repos โ Need Docker images
Can't access other teams' code โ Challenging
3. Modern .NET stack?
Requires .NET 8+ for AppHost
Can orchestrate containerized legacy apps
IIS-dependent apps โ Not compatible
If you meet these requirements: There's no reason NOT to use Aspire