Introducing Aspire
What is Aspire, and how can it help you orchestrate your local development experience by modelling your application architecture, and providing a really cool dashboard (among other things)?
Aspire is a really interesting tool for orchestrating your local development experience, integrating with OpenTelemetry, and optionally providing a way to automate deployments. It has the potential to replace manual steps and custom startup scripts with a more declarative and simpler approach.

Originally known as ’.NET Aspire’, the name has recently been tweaked to just ‘Aspire’ to help promote it’s applicability across all kinds of development environments, not just .NET.
Today the latest version of Aspire was demonstrated at .NET Conf 2025. Let’s take a look at what Aspire is, and how it can help you.
The AppHost
At the heart of Aspire is the concept of an ‘AppHost’. This is a .NET project in which you define the services (which could be local applications, containers and even remote services). You also define any dependencies between those services, and can use that to then provide configuration information (connection strings, endpoint URLs etc) so that they can communicate with each other. You’re essentially creating a model of your application architecture.
Importantly, while the AppHost is a .NET project (possibly even a .NET 10 file-based application to make it really simple), this is the only thing that needs .NET. All the other services can be written in pretty much any language or framework you like. They could be Node.js applications, Python, Java, or anything else (including .NET of course!).
Here’s an example AppHost file:
var builder = DistributedApplication.CreateBuilder(args);
var mongo = builder.AddMongoDB("mongo")
.WithDataVolume();
var api = builder.AddProject<Projects.aspire_starter_ApiService>("apiservice")
.WithReference(mongo)
.WaitFor(mongo);
var frontend = builder.AddViteApp("frontend", "../frontend")
.WithPnpm()
.WithReference(api)
.WaitFor(api);
builder.Build().Run();
In just those ~15 lines of code, we’re describing an application which has a MongoDB database, a .NET API service, and a Vite frontend web app:
- We create a
buildervariable (an instance ofIDistributedApplicationBuilder) that will then use to define and wire up the services. - The MongoDB database is hosted as a Docker container, with a data volume to persist data between runs.
- The API service is a .NET project that references the MongoDB service and waits for it to be ready before starting.
- The frontend is a Vite application that references the API service and exposes an HTTP endpoint.
With that in place, all you need to do is run this AppHost project (either with dotnet run or via the Aspire CLI with aspire run), and Aspire will figure out the order to start the services, then start them up while providing the requested configuration information.
WaitFor
The WaitFor method tells Aspire that this service should wait until the referenced service is in a ‘running’ state. Services may define health checks that Aspire will use to determine when a service is truly ready. SQL Server is a good example - where even though the main SQL Server process may have started, the database engine won’t be ready immediately as there are a number of housekeeping tasks it needs to complete before all the databases become available for use.
WithReference
The WithReference method causes Aspire to inject environment variables into the service which provide a way for it to connect to the referenced service.
For the above code, the references to Mongo generate connection string environment variable of the form ConnectionStrings__mongo. The API service can use that environment variable to connect to the MongoDB database.
The reference to the API service generate environment variables APISERVICE_HTTP and APISERVICE_HTTPS which provide the URLs that the frontend can use to connect to the API.
There are overloads of WithReference that allow you to customise naming scheme of the environment variables, and if that isn’t enough you can always add a custom environment variable with WithEnvironment.
The dashboard
One of the key features of Aspire is that you’re not just left to wonder how things are going. A really cool dashboard is provided that gives you both the high-level overview of all your services, as well as being able to drill into specific service configuration and logs, and even see OpenTelemetry traces and metrics (if you have OpenTelemetry added to your services).

Clicking on the ‘frontend’ service shows the configuration that Aspire has provided to that service, including the environment variables that were injected:

View all the console output from services (or filter to just a specific service):

If your services are instrumented with OpenTelemetry, you can see structured logs, traces and metrics:



Aspire is resilient enough that for example if you forget to start Docker, it will let you know that services depending on that can’t start.

The cool thing though is you don’t need to restart Aspire. If you start Docker, Aspire will notice that it is now available, and will start the services that were waiting on it. You can see the status change in real-time in the dashboard as services become healthy. Note that the other services (which need to wait for Mongo) are not even started yet.

Publishing and deploying
Aspire can optionally prepare the application for deployment by ‘publishing’ parameterised assets. You can then ‘deploy’ those assets to a specific target environment.
Currently, the following deployment targets are supported:
- Docker / Docker Compose
- Kubernetes
- Azure Container Apps
- Azure App Services
Some service types may support these targets natively, while others may need additional configuration. There are also non-Azure targets available too. For example there’s support for AWS with the Aspire.Hosting.AWS package. See https://github.com/aws/integrations-on-dotnet-aspire-for-aws for more information.
For example, adding this line to the AppHost above:
builder.AddDockerComposeEnvironment("aspire-starter");
and then running the publish command:
aspire publish
causes a docker-compose.yaml and .env files to be created:
services:
aspire-starter-dashboard:
image: "mcr.microsoft.com/dotnet/nightly/aspire-dashboard:latest"
expose:
- "18888"
- "18889"
networks:
- "aspire"
restart: "always"
mongo:
image: "docker.io/library/mongo:8.0"
environment:
MONGO_INITDB_ROOT_USERNAME: "admin"
MONGO_INITDB_ROOT_PASSWORD: "${MONGO_PASSWORD}"
expose:
- "27017"
volumes:
- type: "volume"
target: "/data/db"
source: "aspire-starter.apphost-06ac3d63aa-mongo-data"
read_only: false
networks:
- "aspire"
apiservice:
image: "${APISERVICE_IMAGE}"
environment:
OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES: "true"
OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES: "true"
OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY: "in_memory"
ASPNETCORE_FORWARDEDHEADERS_ENABLED: "true"
HTTP_PORTS: "${APISERVICE_PORT}"
ConnectionStrings__mongo: "mongodb://admin:${MONGO_PASSWORD}@mongo:27017?authSource=admin&authMechanism=SCRAM-SHA-256"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://aspire-starter-dashboard:18889"
OTEL_EXPORTER_OTLP_PROTOCOL: "grpc"
OTEL_SERVICE_NAME: "apiservice"
expose:
- "${APISERVICE_PORT}"
depends_on:
mongo:
condition: "service_started"
networks:
- "aspire"
networks:
aspire:
driver: "bridge"
volumes:
aspire-starter.apphost-06ac3d63aa-mongo-data:
driver: "local"
Just to repeat, the publish and deployment aspects of Aspire are entirely optional. If you’ve already got Infrastructure as Code and/or CI/CD pipelines you can continue to use those, and just use Aspire for local development. But if you haven’t got them in place, Aspire may be useful to help you get started.
Learning more and getting started
Head over to the new home of Aspire at https://aspire.dev to find more details about how Aspire works and how to get started.
(There is also the old documentation site which is part of Microsoft Learn, but as I understand it the plan is for that content to be gradually migrated to the new site)
Oh, and finally keep an eye out for my presentation happening as part of the ‘Community’ day of .NET Conf 2025 where I’ll be showing how well Aspire works with non-.NET applications!