Every developer has a horror story about local environment setup. Spending the first two days of a new job installing SQL Server, configuring blob storage, setting up a redis instance, fighting port conflicts, and finally getting something to run — only to discover it works completely differently on your colleague's machine.
For years, our answer to this was Docker Compose: a YAML file describing every service the application depends on, wired together into a local development stack. It worked, mostly. But it was fragile, developer-hostile, and produced far more "it works on my machine" moments than it should have.
Then we started using .NET Aspire, and our local development experience changed overnight. This is how we use it, why it matters, and what we'd tell you if you're considering it for your next .NET project.
The problem Aspire actually solves
Modern .NET applications are rarely a single executable talking to a single database. A typical SaaS platform we build looks something like this:
- An ASP.NET Core web application
- A PostgreSQL or SQL Server database
- Azure Blob Storage for file uploads (locally emulated via Azurite)
- Hangfire for background job processing
- A secondary service or API for a specific domain
- Sometimes a frontend dev server running separately
- Ngrok tunnels for testing webhook integrations with Stripe, EmailJS, or similar
To run this locally, every developer historically needed to:
- Install the right versions of everything (and hope the versions match)
- Configure connection strings in half a dozen
appsettings.jsonfiles - Remember to start each service in the right order
- Debug when one of them crashes silently
- Tell the new developer why their setup is different from yours
Docker Compose helped with the version problem but introduced its own: slow rebuilds, opaque failures, and a YAML file that became the most important (and most fragile) artefact in the repository.
Aspire replaces all of this with a single C# project called the AppHost. You describe your local dev topology in C# — not YAML, not JSON, just typed code with IntelliSense — and Aspire takes care of the rest.
What an AppHost actually looks like
Here's a simplified version of the kind of AppHost we use on one of our multi-tenant SaaS projects:
var builder = DistributedApplication.CreateBuilder(args);
// SQL Server container, persisted so data survives restarts
var sql = builder
.AddSqlServer("sql")
.WithDataVolume()
.WithHostPort(1433);
var db = sql.AddDatabase("appdb");
// Azurite - local Azure Storage emulator
var storage = builder
.AddAzureStorage("storage")
.RunAsEmulator();
var blobs = storage.AddBlobs("blobs");
// The main web application
builder
.AddProject<Projects.AppHost_WebApp>("webapp")
.WithReference(db)
.WithReference(blobs)
.WaitFor(db);
builder.Build().Run();
That's the complete local development environment. When a developer runs this project in their IDE, Aspire:
- Pulls the SQL Server container and starts it
- Starts Azurite
- Injects connection strings into the web app via environment variables automatically
- Starts the web app
- Opens a dashboard showing the status of every service, their logs, and distributed traces between them
- Cleans everything up when the debugger detaches
No docker-compose.yml. No connection strings in appsettings.Development.json. No "what port is SQL running on?" Slack messages. Just a single run configuration that brings up the entire stack.
The dashboard is the quiet superpower
The part of Aspire that doesn't get enough attention is the dashboard. When you run the AppHost, Aspire spins up a local web UI showing every resource, its status, live logs, health checks, and the environment variables injected into each one. Everything you need in one place, no more hunting across four terminal windows.
But the real magic is the telemetry.
Telemetry that just works
Here's the thing most articles gloss over: Aspire wires up OpenTelemetry automatically. Every project added to the AppHost gets distributed tracing, structured logs, and metrics without writing a single line of instrumentation code. It's one of those features that sounds incremental until you actually use it.
In practice, this means:
-
Distributed traces across services. When a request comes into your web app, you can watch it flow through your controllers, into Entity Framework Core, out to SQL Server, into a background job, and back — as a single visual trace in the dashboard. Every span, every timing, every database query, laid out in front of you.
-
Structured logs, correlated to traces. Logs aren't just a wall of text — they're tagged with the trace ID of the request they belong to. Click a slow request in the traces view and you see exactly the logs that request produced. No more grepping terminal windows trying to reconstruct what happened.
-
Metrics for HTTP, database, cache, and runtime. Request rates, response times, database query counts, memory usage, GC behaviour — all visible in real time. The kind of observability that in production would cost you Datadog or Application Insights, running for free on your laptop.
The practical effect: you find problems earlier. We've caught N+1 query bugs, missing database indexes, accidental synchronous calls inside async methods, and slow third-party API dependencies — all during local development, just by glancing at the traces view in the dashboard before shipping code. These are the bugs that usually show up in production as mysterious performance regressions, and Aspire's telemetry surfaces them before they ever leave your machine.
For a platform like REBLL Tickets, where we have the web app, SQL Server, Azurite, and ngrok all running during local development, the telemetry view is the single source of truth. When something doesn't feel right, you don't guess — you look at the trace.
What we use it for in real projects
Across our active SaaS builds — REBLL, RSRVD, and CyberAssistGO — Aspire handles:
- Database containers (SQL Server and PostgreSQL depending on the project), with persistent data volumes so developers don't lose test data between sessions
- Azurite for blob storage, queues, and tables
- Ngrok tunnels for webhook development — Stripe and Square both need publicly-reachable HTTPS endpoints, and Aspire can start and manage the tunnel as part of the AppHost
- The main web application and any secondary services, wired together with automatic service discovery and injected configuration
- Background job workers running as a separate project so developers can debug Hangfire in isolation
The net effect: new developer onboarding for these projects dropped from about two days to under twenty minutes. Check out the repo, run the AppHost, everything is there.
The bit most articles skip: you don't have to deploy it
A common misconception is that Aspire is a production deployment technology. It isn't — at least, not in the way we use it. The AppHost project is for local development. In production, each service is deployed independently to Azure Container Apps, Azure App Service, or wherever it needs to live. The AppHost isn't deployed at all.
This is actually the cleanest mental model: Aspire is a local orchestration tool. Production uses Azure infrastructure as code (we use Bicep). The two don't need to know about each other.
Microsoft does ship Aspire deployment tooling for Azure Container Apps, and it's perfectly usable if that fits your project. But you shouldn't feel obligated to use it. Using Aspire for local dev and Bicep for production is a completely valid (and in our opinion, cleaner) architecture.
The gotchas
It's not all sunshine. Things to be aware of:
-
Aspire moves fast. Breaking changes between minor versions are common. Pin your package versions and test upgrades carefully.
-
Resource startup times add up. On a cold start, spinning up SQL Server + Azurite + the web app takes 30-60 seconds. Fast enough, but not instant. Keep the AppHost running between debug sessions.
-
Some Aspire integrations are newer than others. The core SQL Server, PostgreSQL, and Azurite integrations are rock solid. Some of the more niche ones (certain queue providers, specific observability backends) are still maturing.
-
Windows devs need Docker Desktop or Podman. Aspire uses containers under the hood. If your team is on Windows without Docker Desktop licences, you'll need an alternative runtime.
-
It's a .NET 8+ technology. If you're still on .NET Framework or older .NET versions, it's not an option.
Why we recommend it for new .NET projects
If you're starting a new .NET project in 2026, Aspire should be the first tool you reach for. The alternative is spending a week building a docker-compose.yml, writing onboarding docs that immediately go stale, and then watching new developers struggle for days. Aspire collapses all of that into a single C# project that anyone with an IDE can run.
If you already have an existing project without Aspire, adding it is almost risk-free. The AppHost is additive — it doesn't require any changes to your production deployment, your CI pipeline, or your code. You can introduce it gradually, start with just a database container, and expand from there.
At Zim Digital, we've yet to start a .NET project where Aspire wasn't the right answer for local development. The productivity difference is meaningful enough that we'd struggle to go back.
Want help adopting Aspire on your project?
If you're building a .NET application and want to modernise your local development experience — or if you're starting something new and want to get the foundations right — get in touch. We've deployed Aspire on multiple production SaaS platforms and can help you avoid the pitfalls.
Related reading
Why We Built the REBLL Ticket Scanner in Flutter — and Why It Has to Work Offline
Real-world lessons from shipping a production ticket scanning app for festivals and events with Flutter. One codebase, two app stores, and an offline-first architecture that doesn't queue 5,000 punters at the gate when the venue WiFi dies.
Software Development for Northwest UK SMEs: What We See Working in 2026
Practical observations from a Northwest UK software consultancy on what's actually moving the needle for SMEs in Manchester, Liverpool, Preston, and beyond — and what's still a waste of time.