Why Native AOT Matters for the Aspire Dashboard
Developers often restart the .NET Aspire dashboard whenever they change an AppHost, update a service, or investigate a local development issue. Every restart introduces some startup overhead, and that delay becomes noticeable when it happens repeatedly throughout the day.
The Aspire dashboard provides a central view of application resources, structured logs, distributed traces, and metrics. It is useful because developers can investigate application behavior without switching between multiple monitoring tools.
Microsoft introduced Native Ahead-of-Time (AOT) compilation for the Aspire dashboard in Aspire 13.6, announced on October 6, 2026. The change reduces startup time, removes the dashboard executable's dependency on a separately installed .NET runtime, and allows the dashboard to use newer .NET features without depending on whichever runtime happens to be installed on a developer's machine.
The interesting part is how Microsoft made this possible. The work involved more than changing a project property. It required improvements across Blazor, Fluent UI, Dapper, JSON serialization, and the dashboard's packaging process.
What Is Native AOT in .NET?
Most .NET applications are compiled into Intermediate Language (IL). When the application runs, the Just-in-Time (JIT) compiler converts methods into native machine code as they are needed.
Native AOT changes that process by compiling the application into native machine code during publishing.
Area | Traditional .NET deployment | Native AOT deployment |
|---|
Compilation | IL compiled into machine code at runtime | Native machine code generated during publishing |
JIT compilation | Available at runtime | Not used by the published application |
Runtime dependency | Requires a compatible .NET runtime for framework-dependent deployment | Does not require a separately installed .NET runtime |
Reflection and dynamic code | Broad runtime capabilities are available | Some patterns require explicit metadata or alternative implementations |
Platform compatibility | Depends on the deployment model and target runtime | Requires a binary published for the target OS and architecture |
Native AOT does not mean that an application can run on every operating system from the same executable. The published binary targets a particular operating system and architecture, so separate artifacts may be required for Windows, Linux, and macOS.
It also does not automatically guarantee a smaller deployment or faster execution for every workload. The benefit depends on the application's architecture, dependencies, and startup behavior.
For the Aspire dashboard, startup is particularly important because the process is frequently launched and restarted during development.
What Performance Improvements Did Microsoft Report?
Microsoft measured the time required for the dashboard's page to become visible to the user.
Measurement | Traditional JIT deployment | Native AOT dashboard |
|---|
Median page-visible startup time | 1,429 ms | 491 ms |
Relative improvement | Baseline | Approximately 66% lower startup time |
The difference is approximately 938 milliseconds per startup. Native AOT reduced the measured median page-visible startup time from about 1.43 seconds to about 0.49 seconds.
This is a vendor-reported result, not a universal guarantee. Hardware, operating-system behavior, dashboard configuration, and the measurement methodology can influence startup time.
The result nevertheless illustrates why Native AOT is useful for developer tooling. Saving nearly a second may seem minor in isolation, but repeated restarts make the cumulative improvement more noticeable.
The benefit also extends beyond initial process startup. Without JIT compilation, the dashboard avoids the first-use compilation work that would otherwise occur when particular pages or features are exercised after a restart.
Smaller Runtime Footprint and Simpler Distribution
Native AOT changes how the dashboard is packaged.
In a traditional deployment, the dashboard executable and its application files can be relatively small, but a compatible .NET runtime must also be available. A self-contained deployment bundles the runtime, which increases the overall deployment size.
Microsoft reported the following comparison for the dashboard:
Deployment component | Traditional deployment | Native AOT |
|---|
Dashboard application | 66.35 MB | 110.22 MB |
Additional .NET runtime | Approximately 116.73 MB | Not required separately |
Combined size | Approximately 183.08 MB | 110.22 MB |
The native executable is larger than the traditional application files alone. The overall package is smaller because it no longer needs the separately packaged runtime.
These measurements describe Microsoft's reported packaging comparison. Actual artifact sizes vary by target platform, build configuration, and included dependencies.
Why This Matters for Containers
The same architectural change can simplify container images.
A traditional self-contained or framework-dependent deployment may need additional runtime components or a suitable .NET runtime image. A Native AOT executable can instead use a compatible base image that contains the operating-system dependencies required by the binary.
That creates an opportunity to reduce image size and deployment overhead.
However, Native AOT does not mean the application can run in an empty container. The executable still needs compatible operating-system libraries, certificates where required, configuration, and any other native dependencies.
For production deployments, test the final image rather than assuming that a smaller application executable automatically produces a working minimal container.
Why the Dashboard Needed Changes Across the Stack
The Aspire dashboard is a substantial ASP.NET Core application. It includes a Blazor Web App frontend, Fluent UI components, gRPC and HTTP endpoints for receiving telemetry, SQLite persistence through Dapper, and authentication options.
Each of these components introduces potential challenges for Native AOT.
The compiler needs to determine which code and metadata the application requires before it runs. Features that depend on discovering types through reflection, generating code dynamically, or serializing arbitrary objects at runtime can conflict with trimming and ahead-of-time compilation.
Microsoft addressed these issues through changes in several dependencies.
Blazor Support
Blazor traditionally relies on runtime reflection for component discovery, parameter handling, dependency injection, event dispatch, and serialization in interactive applications.
The Aspire dashboard team worked with the Blazor team to add the framework support needed for its Native AOT scenario. The changes included generated JSON metadata for Blazor circuits and alternatives to runtime code generation for certain form operations.
This allowed the dashboard to retain its existing Blazor-based user interface rather than replacing it with a different frontend framework.
An important qualification is that the Blazor Native AOT support used for this dashboard is experimental. The Aspire implementation does not mean Native AOT publishing is generally supported for every Blazor Web App.
Fluent UI Compatibility
The dashboard uses Fluent UI components for its grids, dialogs, filters, charts, and telemetry views.
Some UI-library functionality relied on runtime generic reflection or dynamically discovered metadata. Those patterns needed alternatives that the Native AOT compiler could understand.
The work included changes to grid formatting, field validation, JSON metadata generation, and related UI functionality. The dashboard also upgraded to Fluent UI v5 to consume the required compatibility improvements.
This demonstrates a broader lesson: adopting Native AOT in a mature application often requires checking the entire dependency graph, not just the application's own code.
Dapper and Database Access
The dashboard uses SQLite for persistence and Dapper for database access.
Dapper's conventional mapping features can rely on runtime metadata and reflection. Its Native AOT-compatible counterpart, Dapper.AOT, generates code during compilation to handle supported database operations.
The Aspire dashboard also uses dynamic SQL parameters. Supporting those operations required improvements to how Dapper.AOT handles parameter bags and output values.
This approach moves work that would otherwise happen at runtime into generated code, making the behavior more suitable for Native AOT.
Using Source-Generated JSON Metadata
One common requirement when adopting Native AOT is replacing reflection-based JSON serialization with source-generated metadata.
Consider a simple telemetry-related model:
using System.Text.Json;
using System.Text.Json.Serialization;
public sealed record ServiceStatus(
string Name,
bool Healthy,
int ActiveRequests);
[JsonSerializable(typeof(ServiceStatus))]
internal partial class DashboardJsonContext
: JsonSerializerContext
{
}
The JsonSerializable attribute tells the source generator to create serialization metadata for ServiceStatus during compilation.
The application can then serialize an instance through the generated context:
var status = new ServiceStatus(
Name: "CatalogApi",
Healthy: true,
ActiveRequests: 12);
string json = JsonSerializer.Serialize(
status,
DashboardJsonContext.Default.ServiceStatus);
This example illustrates the general technique used to make JSON handling more compatible with trimming and Native AOT. It is not a complete replacement for the Aspire dashboard's internal serialization configuration.
The important difference is that the serializer can use metadata generated at build time rather than discovering the model's properties through unrestricted runtime reflection.
When applying this pattern to a real application, register every relevant model type and verify that nested objects, collections, polymorphic types, and custom converters are handled correctly.
The Runtime Compatibility Problem
Before this change, the Aspire dashboard targeted .NET 8, the oldest supported .NET version in its previous deployment arrangement. It could run on a newer installed runtime through framework roll-forward.
That arrangement introduced a compatibility risk.
A Blazor Web App may depend on framework and JavaScript assets that match the runtime version it was built for. If the dashboard's assets were produced for .NET 8 while the machine ran a newer runtime, mismatches could cause bugs.
Native AOT changes this model because the dashboard ships its compiled framework code and assets together. The dashboard targets .NET 11, so the server-side components and corresponding assets are aligned with the version used to build the application.
This also lets the dashboard adopt newer .NET APIs and fixes without waiting for the previous minimum runtime to reach end of support.
The distinction matters when the dashboard is used alongside applications targeting different .NET versions. The dashboard's runtime and the monitored applications' runtimes are separate concerns.
How to Try the Native AOT Dashboard
The Native AOT dashboard is available through Aspire 13.6. For the normal AppHost workflow, the appropriate dashboard is selected automatically when using the supported Aspire tooling.
To use the dashboard independently, run the Aspire CLI command:
aspire dashboard run
The standalone dashboard can receive OpenTelemetry data from applications that export telemetry through the OpenTelemetry Protocol (OTLP). This is useful when monitoring applications that do not use Aspire orchestration, including services written in other languages.
For example, an application can be configured to export OTLP telemetry to the standalone dashboard's endpoint. The exact endpoint and protocol depend on the dashboard configuration.
The dashboard does not automatically instrument an application merely because it is running. Applications must have suitable OpenTelemetry instrumentation and exporters configured.
For security, retain the default authentication behavior unless there is a specific, controlled reason to change it. Dashboard telemetry and configuration can expose sensitive information.
Practical Considerations Before Adopting Native AOT
Native AOT is valuable when startup time, distribution, and runtime consistency matter. However, it is not the right publishing model for every .NET application.
Before adopting it, consider these points:
Review dependencies. Check whether libraries rely on reflection, runtime code generation, or dynamic assembly loading.
Resolve compiler warnings. Trimming and AOT warnings may indicate code paths that could fail after publishing. Do not suppress warnings without understanding their cause.
Test the published artifact. A successful development build does not prove that the Native AOT executable behaves correctly.
Build for the target platform. Publish separate binaries or container images for the operating systems and architectures you support.
Measure the correct metric. Compare cold-start time, first-page visibility, memory use, and package size under consistent conditions.
Verify framework support. Experimental framework features should be treated differently from generally supported publishing capabilities.
For a dashboard or command-line tool that starts frequently, these trade-offs can be worthwhile. For a long-running service with a complex dependency graph, the benefit should be evaluated against the engineering effort required to make the application AOT-compatible.
Conclusion
Bringing Native AOT to the .NET Aspire dashboard improves more than startup speed. It reduces the need for a separately installed .NET runtime, provides a more consistent runtime environment, and creates opportunities for simpler packaging.
Microsoft's reported measurements show a reduction in median page-visible startup time from 1,429 milliseconds to 491 milliseconds. Achieving that result required changes to Blazor, Fluent UI, Dapper, JSON serialization, and the dashboard's deployment architecture.
The main lesson for .NET developers is that Native AOT is an architectural decision, not just a project-file setting. Successful adoption requires compatible dependencies, explicit handling of metadata, careful publishing, and testing of the final artifact.
For tools that restart frequently, the investment can deliver a more responsive development experience and a simpler deployment model. For other applications, measure the actual benefits and verify framework support before making the switch.
Join the conversation! Your thoughts help the community grow.