¿Qué es .NET Aspire?

.NET Aspire es un stack de desarrollo cloud-native presentado por Microsoft para facilitar la creación de aplicaciones distribuidas y observables. No es un framework nuevo, sino un conjunto de herramientas, integraciones y abstracciones que se ubican encima de .NET 8/9 para reducir la fricción operacional desde el primer día de desarrollo.

En términos prácticos, Aspire te da tres cosas fundamentales: un modelo de orquestación declarativo, un conjunto de componentes (integraciones con Redis, PostgreSQL, RabbitMQ, Azure Service Bus, etc.) y un dashboard de observabilidad que funciona en local sin configurar nada extra.

Instalación y estructura del proyecto

Para comenzar necesitas .NET 9 SDK y la plantilla de Aspire instalada:

# Instalar la plantilla de .NET Aspire
dotnet workload install aspire

# Crear una nueva solución con Aspire
dotnet new aspire-starter -o SistemaVentas
cd SistemaVentas

La solución resultante tiene esta estructura:

SistemaVentas/
├── SistemaVentas.AppHost/        # Orquestador principal
├── SistemaVentas.ServiceDefaults/ # Configuración compartida
├── SistemaVentas.ApiService/     # Tu API backend
└── SistemaVentas.Web/            # Frontend Blazor o MVC

El AppHost: corazón del orquestador

El proyecto AppHost es donde defines toda la topología de tu aplicación de forma declarativa. En lugar de mantener múltiples archivos docker-compose.yml o scripts de inicio, todo vive en C#:

var builder = DistributedApplication.CreateBuilder(args);

// Agregar base de datos PostgreSQL
var postgres = builder.AddPostgres("db-ventas")
    .WithDataVolume()
    .WithPgAdmin();

var catalogoDb = postgres.AddDatabase("catalogo");

// Agregar Redis para caché de sesiones
var cache = builder.AddRedis("cache-sesiones")
    .WithRedisCommander();

// Definir el servicio de API con sus dependencias
var apiService = builder
    .AddProject<Projects.SistemaVentas_ApiService>("api-ventas")
    .WithReference(catalogoDb)
    .WithReference(cache)
    .WaitFor(catalogoDb);

// Frontend con referencia al API
builder.AddProject<Projects.SistemaVentas_Web>("web-frontend")
    .WithReference(apiService)
    .WithExternalHttpEndpoints();

builder.Build().Run();

Nota clave: El método WaitFor() garantiza que el servicio de API no arranque hasta que la base de datos esté lista, eliminando condiciones de carrera en el arranque local y en CI/CD.

ServiceDefaults: resiliencia lista para usar

El proyecto ServiceDefaults centraliza configuraciones que antes repetías en cada microservicio: health checks, OpenTelemetry, service discovery y políticas de resiliencia con Polly.

C#SistemaVentas.ServiceDefaults/Extensions.cs

public static IHostApplicationBuilder AddServiceDefaults(
    this IHostApplicationBuilder builder)
{
    builder.ConfigureOpenTelemetry();   // Trazas + métricas automáticas
    builder.AddDefaultHealthChecks();   // /health y /alive
    builder.Services.AddServiceDiscovery(); // Resolución dinámica

    builder.Services.ConfigureHttpClientDefaults(http =>
    {
        // Resiliencia por defecto en todos los HttpClient
        http.AddStandardResilienceHandler();
        http.AddServiceDiscovery();
    });

    return builder;
}

Luego en cada servicio simplemente llamas:

var builder = WebApplication.CreateBuilder(args);

builder.AddServiceDefaults(); // Una línea para todo
builder.AddNpgsqlDbContext<CatalogoDbContext>("catalogo");
builder.AddRedisDistributedCache("cache-sesiones");

Comunicación entre servicios con service discovery

Uno de los problemas clásicos en microservicios locales es hardcodear puertos. Con Aspire, los servicios se referencian por nombre y el runtime resuelve las URLs automáticamente, igual que en Kubernetes pero sin necesitar un clúster:

// Registro del cliente tipado
builder.Services.AddHttpClient<VentasApiClient>(client =>
{
    // "api-ventas" es el nombre definido en AppHost
    // Aspire resuelve la URL real en tiempo de ejecución
    client.BaseAddress = new Uri("https+http://api-ventas");
});

// Uso en un componente Blazor
public class VentasApiClient(HttpClient httpClient)
{
    public async Task<List<ProductoDto>> ObtenerCatalogo()
    {
        return await httpClient
            .GetFromJsonAsync<List<ProductoDto>>("/api/productos")
            ?? [];
    }
}

Dashboard de observabilidad

Al ejecutar dotnet run en el AppHost, Aspire levanta automáticamente un dashboard local en https://localhost:15888 con trazas distribuidas, métricas, logs estructurados y estado de salud de cada servicio, todo potenciado por OpenTelemetry sin configuración manual.

Producción: El dashboard de desarrollo no es para producción. En Azure puedes exportar la telemetría a Azure Monitor / Application Insights usando el mismo pipeline de OpenTelemetry sin cambiar el código de tus servicios. En AWS o GCP puedes apuntar a cualquier backend compatible con OTLP.

Despliegue: de local a la nube

Aspire genera automáticamente manifiestos de despliegue. Para Azure Container Apps basta con usar azd:

# Inicializar Azure Developer CLI con Aspire
azd init --template aspire

# Desplegar toda la solución (genera Bicep + configura ACA)
azd up

Si prefieres Kubernetes, puedes generar el manifiesto con:

dotnet run --project SistemaVentas.AppHost -- \
  --publisher manifest \
  --output-path ../manifests/aspire-manifest.json

Herramientas como Aspir8 convierten ese manifiesto en objetos de Kubernetes (Deployments, Services, ConfigMaps) listos para aplicar con kubectl.


¿Cuándo usar .NET Aspire?

Aspire brilla especialmente cuando tu aplicación tiene más de dos servicios que se comunican entre sí, necesitas consistencia en observabilidad entre equipos, o quieres reducir la brecha entre el entorno local y producción. No es un reemplazo de Kubernetes ni de Docker Compose para todos los casos, sino una capa de abstracción que hace que el trabajo del día a día sea significativamente más productivo.

Para proyectos con un solo servicio o equipos no familiarizados con el ecosistema .NET moderno, la curva de adopción inicial puede superar los beneficios a corto plazo. Pero para equipos de plataforma que buscan estandarizar cómo se construyen servicios distribuidos en .NET, la propuesta de valor es muy clara.

.NET Aspire representa una apuesta seria de Microsoft por el desarrollo cloud-native desde el día cero. Al combinar orquestación declarativa, resiliencia por convención y observabilidad integrada en un solo stack cohesionado, reduce drásticamente el tiempo que pasa entre “tengo una idea” y “tengo algo distribuido funcionando localmente”. Si trabajas con .NET y construyes sistemas con múltiples servicios, vale la pena explorarlo ahora.

Por favor síguenos y dale me gusta: