Agent skill
aspire
Use when building cloud-native distributed applications with .NET Aspire. Covers the app host orchestration model, service defaults, built-in components (Redis, PostgreSQL, RabbitMQ), dashboard, health checks, and deployment to Azure Container Apps. USE FOR: orchestrating multi-service .NET applications, adding Redis/PostgreSQL/RabbitMQ with one line, built-in OpenTelemetry observability, local development dashboard for distributed apps, service discovery between projects DO NOT USE FOR: single-project monolithic applications without external dependencies, Kubernetes-native deployments with Helm (use standard containers), non-.NET polyglot microservices without .NET orchestration, Dapr sidecar architecture (use dapr)
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/aspire
Metadata
Additional technical details for this skill
- author
- Tyler-R-Kendrick
- version
- 1.0.0
- displayName
- .NET Aspire
SKILL.md
.NET Aspire
Overview
.NET Aspire is an opinionated framework for building observable, production-ready, cloud-native distributed applications. It provides an app host project for orchestrating multi-service applications, service defaults for consistent configuration (OpenTelemetry, health checks, resilience), and pre-built components for common infrastructure like Redis, PostgreSQL, RabbitMQ, and Azure services. The Aspire dashboard provides real-time visibility into traces, logs, and metrics during local development.
Project Structure
MyApp/
MyApp.AppHost/ # Orchestration project (references all services)
MyApp.ServiceDefaults/ # Shared configuration (telemetry, health checks)
MyApp.Api/ # Web API project
MyApp.Worker/ # Background worker project
MyApp.Web/ # Frontend project
Getting Started
dotnet new aspire-starter -n MyApp
# Creates AppHost, ServiceDefaults, Api, and Web projects
App Host (Orchestration)
The AppHost project defines the distributed application topology: which services to run, what infrastructure they need, and how they connect.
// MyApp.AppHost/Program.cs
var builder = DistributedApplication.CreateBuilder(args);
// Infrastructure resources
var cache = builder.AddRedis("cache")
.WithRedisCommander(); // Adds Redis Commander UI
var postgres = builder.AddPostgres("postgres")
.WithPgAdmin() // Adds pgAdmin UI
.WithDataVolume(); // Persists data across restarts
var db = postgres.AddDatabase("appdb");
var rabbit = builder.AddRabbitMQ("messaging")
.WithManagementPlugin(); // Adds RabbitMQ management UI
// Application projects
var api = builder.AddProject<Projects.MyApp_Api>("api")
.WithReference(db)
.WithReference(cache)
.WithReference(rabbit)
.WithExternalHttpEndpoints();
builder.AddProject<Projects.MyApp_Worker>("worker")
.WithReference(db)
.WithReference(rabbit);
builder.AddProject<Projects.MyApp_Web>("web")
.WithReference(api)
.WithExternalHttpEndpoints();
builder.Build().Run();
Service Defaults
Shared configuration that every service in the application uses.
// MyApp.ServiceDefaults/Extensions.cs
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using OpenTelemetry;
using OpenTelemetry.Metrics;
using OpenTelemetry.Trace;
public static class Extensions
{
public static IHostApplicationBuilder AddServiceDefaults(
this IHostApplicationBuilder builder)
{
builder.ConfigureOpenTelemetry();
builder.AddDefaultHealthChecks();
builder.Services.AddServiceDiscovery();
builder.Services.ConfigureHttpClientDefaults(http =>
{
http.AddStandardResilienceHandler();
http.AddServiceDiscovery();
});
return builder;
}
public static IHostApplicationBuilder ConfigureOpenTelemetry(
this IHostApplicationBuilder builder)
{
builder.Logging.AddOpenTelemetry(logging =>
{
logging.IncludeFormattedMessage = true;
logging.IncludeScopes = true;
});
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics =>
{
metrics
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddRuntimeInstrumentation();
})
.WithTracing(tracing =>
{
tracing
.AddAspNetCoreInstrumentation()
.AddHttpClientInstrumentation()
.AddEntityFrameworkCoreInstrumentation();
});
builder.AddOpenTelemetryExporters();
return builder;
}
public static IHostApplicationBuilder AddDefaultHealthChecks(
this IHostApplicationBuilder builder)
{
builder.Services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
return builder;
}
public static WebApplication MapDefaultEndpoints(this WebApplication app)
{
app.MapHealthChecks("/health");
app.MapHealthChecks("/alive", new HealthCheckOptions
{
Predicate = r => r.Tags.Contains("live")
});
return app;
}
}
Service Project Configuration
// MyApp.Api/Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
// Aspire component for PostgreSQL with EF Core
builder.AddNpgsqlDbContext<AppDbContext>("appdb");
// Aspire component for Redis caching
builder.AddRedisDistributedCache("cache");
// Aspire component for RabbitMQ
builder.AddRabbitMQClient("messaging");
builder.Services.AddControllers();
var app = builder.Build();
app.MapDefaultEndpoints();
app.MapControllers();
app.Run();
Built-in Components
| Component | NuGet Package | AddXxx Method |
|---|---|---|
| PostgreSQL (EF Core) | Aspire.Npgsql.EntityFrameworkCore |
AddNpgsqlDbContext<T> |
| PostgreSQL (Npgsql) | Aspire.Npgsql |
AddNpgsqlDataSource |
| Redis (Caching) | Aspire.StackExchange.Redis.DistributedCaching |
AddRedisDistributedCache |
| Redis (Output Cache) | Aspire.StackExchange.Redis.OutputCaching |
AddRedisOutputCache |
| RabbitMQ | Aspire.RabbitMQ.Client |
AddRabbitMQClient |
| Azure Blob Storage | Aspire.Azure.Storage.Blobs |
AddAzureBlobClient |
| Azure Service Bus | Aspire.Azure.Messaging.ServiceBus |
AddAzureServiceBusClient |
| Azure Key Vault | Aspire.Azure.Security.KeyVault |
AddAzureKeyVaultClient |
| MongoDB | Aspire.MongoDB.Driver |
AddMongoDBClient |
| Seq (Logging) | Aspire.Seq |
AddSeqEndpoint |
Using Aspire Components in Services
// PostgreSQL with Entity Framework Core
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddNpgsqlDbContext<CatalogDbContext>("catalogdb");
var app = builder.Build();
app.MapGet("/products", async (CatalogDbContext db) =>
await db.Products.ToListAsync());
app.MapPost("/products", async (Product product, CatalogDbContext db) =>
{
db.Products.Add(product);
await db.SaveChangesAsync();
return Results.Created($"/products/{product.Id}", product);
});
// Redis distributed caching
app.MapGet("/products/{id}", async (
int id, CatalogDbContext db, IDistributedCache cache) =>
{
var cacheKey = $"product:{id}";
var cached = await cache.GetStringAsync(cacheKey);
if (cached is not null)
return Results.Ok(JsonSerializer.Deserialize<Product>(cached));
var product = await db.Products.FindAsync(id);
if (product is null) return Results.NotFound();
await cache.SetStringAsync(cacheKey,
JsonSerializer.Serialize(product),
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
});
return Results.Ok(product);
});
Service Discovery and HTTP Clients
// In the API project, call another service by name
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.Services.AddHttpClient<CatalogClient>(client =>
{
// "catalog-api" is resolved via service discovery from the AppHost
client.BaseAddress = new Uri("https+http://catalog-api");
});
var app = builder.Build();
app.MapGet("/orders/{id}/details", async (int id, CatalogClient catalog) =>
{
var products = await catalog.GetProductsForOrderAsync(id);
return Results.Ok(products);
});
public class CatalogClient(HttpClient httpClient)
{
public async Task<List<Product>> GetProductsForOrderAsync(int orderId) =>
await httpClient.GetFromJsonAsync<List<Product>>(
$"/api/orders/{orderId}/products") ?? [];
}
Custom Resources
// Add a container resource for services not built into Aspire
var elasticsearch = builder.AddContainer("elasticsearch", "elasticsearch", "8.12.0")
.WithHttpEndpoint(port: 9200, targetPort: 9200)
.WithEnvironment("discovery.type", "single-node")
.WithEnvironment("xpack.security.enabled", "false")
.WithVolume("es-data", "/usr/share/elasticsearch/data");
builder.AddProject<Projects.MyApp_Api>("api")
.WithReference(elasticsearch);
Environment and Parameters
var builder = DistributedApplication.CreateBuilder(args);
// Parameters (prompted at deploy time or from config)
var adminPassword = builder.AddParameter("admin-password", secret: true);
var postgres = builder.AddPostgres("postgres", password: adminPassword);
// Connection strings from configuration
var apiKey = builder.AddParameter("api-key", secret: true);
builder.AddProject<Projects.MyApp_Api>("api")
.WithEnvironment("ApiKey", apiKey);
Deployment to Azure Container Apps
# Install the azd CLI
winget install microsoft.azd
# Initialize and deploy
azd init
azd up
// AppHost with Azure-specific resources
var builder = DistributedApplication.CreateBuilder(args);
var insights = builder.AddAzureApplicationInsights("insights");
var storage = builder.AddAzureStorage("storage");
var blobs = storage.AddBlobs("blobs");
builder.AddProject<Projects.MyApp_Api>("api")
.WithReference(insights)
.WithReference(blobs);
Best Practices
- Use the AppHost project solely for orchestration (defining resources, references, and endpoints); never put business logic, controllers, or domain code in the AppHost.
- Call
builder.AddServiceDefaults()as the first line in every service project'sProgram.csto ensure consistent OpenTelemetry, health checks, resilience, and service discovery configuration. - Use
WithDataVolume()on database resources (PostgreSQL, Redis) during development to persist data across container restarts rather than re-seeding on every startup. - Prefer Aspire's
AddNpgsqlDbContext<T>("name")over manualDbContextconfiguration because it automatically wires connection strings from service discovery, configures health checks, and adds OpenTelemetry instrumentation. - Use
WithExternalHttpEndpoints()only on services that need external access (API gateways, frontend); internal services should only be reachable through service discovery. - Reference services by name (
https+http://catalog-api) inHttpClient.BaseAddressand let Aspire's service discovery resolve the actual endpoint, rather than hardcodinglocalhost:PORTURLs. - Use
builder.AddParameter("key", secret: true)for sensitive values (API keys, passwords) instead of hardcoding them; Aspire prompts for these duringazd upand stores them securely. - Add
WithManagementPlugin(),WithPgAdmin(), orWithRedisCommander()during development to get admin UIs for infrastructure resources; these are automatically excluded in production deployments. - Run
azd initandazd upfor deploying to Azure Container Apps rather than manually building Docker images and configuring infrastructure. - Open the Aspire Dashboard (automatically launched during
dotnet runon the AppHost) to inspect distributed traces, structured logs, and metrics across all services during local development.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?