April 21st, 2026
0 reactions

Aspire 13.2: Bun Support and Container Enhancements

Senior Software Engineer

If you’ve been following the JavaScript story in Aspire, 13.2 is the kind of release you want to see. Focused, deliberate, and packed with improvements that make a real difference.

Bun support lands for Vite apps. Yarn gets more reliable. Container publishing becomes more predictable. And a handful of debugging and build improvements add up to a noticeably smoother experience.

In other words: better tooling, more building.

Note

To keep this post aligned with the JavaScript thread, the code samples use apphost.ts. If you’d rather author your AppHost in AppHost.cs, the linked aspire.dev docs include C# examples for the same patterns.

⚡ Bun support for Vite apps

Let’s start with the headline. Bun is now a first-class option for Vite apps in Aspire.

import { createBuilder } from './.modules/aspire.js';

// The builder pattern is used to add resources and model their relationship
const builder = await createBuilder();

// We're adding a Vite app, that points to our frontend directory...
// We chain a call to `withBun` to imply that we want the frontend 
// resource to use bun as its package manager.
await builder
  .addViteApp("frontend", "./frontend")
  .withBun();

await builder.build().run();

That is refreshingly clean. Call withBun(), and Aspire knows how to treat your addViteApp() resource like a Bun-backed app instead of assuming npm. No ceremony. No configuration scavenger hunt. Just a single fluent call that works.

Why does this matter? Because Bun is fast, and JavaScript developers tend to notice when tooling is slow.

  • Startup time matters.
  • Install time matters.
  • Feedback loops matter.

If your team already likes Bun, Aspire no longer makes you feel like you’re coloring outside the lines.

And if you don’t use Bun? Fine. npm, Yarn, and pnpm still work. This isn’t Aspire picking favorites. It’s Aspire behaving like the JavaScript ecosystem exists in the real world.

withYarn() got more reliable too

Bun is the shiny headline, but Yarn users get something arguably even more important: fewer headaches. Aspire 13.2 improves reliability for withYarn() with addViteApp(), which is the sort of fix that sounds small right up until it saves you twenty minutes of local dev confusion.

Reliability is a feature in its own right, and this improvement delivers exactly that.

And if your team is still on Yarn, the TypeScript AppHost version stays just as simple:

await builder.addViteApp("frontend", "./frontend")
  .withYarn();

🐳 Container changes that actually help

There are also some genuinely useful container improvements in 13.2 that give you more control and predictability exactly where you need them.

Pull policy is now explicit

If you’re working with Docker Compose publishing, PullPolicy is now a proper setting, including a Never option for “use the local image and do not get creative” workflows.

That’s useful when you’re iterating locally, testing freshly built images, or working in an environment where pulling from a registry is the wrong move. It’s a small change, but it makes container behavior more honest and easier to reason about.

Imagine you’re working in your TypeScript AppHost, and you’ve already added docker compose support:

aspire add docker

You can now add an import for the ImagePullPolicy enum and chain a call to withImagePullPolicy.

import { createBuilder, ImagePullPolicy } from './.modules/aspire.js';

const builder = await createBuilder();

// Adds a Docker Compose publishing environment.
await builder.addDockerComposeEnvironment("compose");

// Add a container based on the myorg/worker:latest image.
// Specify that the image should never be pulled from the registry.
const worker = await builder.addContainer("worker", "myorg/worker:latest")
  .withImagePullPolicy(ImagePullPolicy.Never);

await builder.build().run();

If that reads like “please use the image I already built and leave the registry out of it,” that’s because it is. The Docker Compose deployment docs spell out the same mapping directly.

PostgreSQL 18+ just works

PostgreSQL 18 changed its internal data directory layout. Naturally, that means volume mapping got weird.

Aspire 13.2 now handles the data volume path correctly for PostgreSQL 18 and later. If you’re running newer Postgres versions, persistence keeps working seamlessly with no extra configuration required.

import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

// Add a postgres server resource with a data volume.
const postgres = await builder.addPostgres("postgres")
  .withDataVolume({ isReadOnly: false });

// From the postgres server resource add a database named 'appdb'
const appDb = await postgres.addDatabase("appdb");

// Add a node app for our api and reference the database.
await builder
  .addNodeApp("api", "./api", "src/index.ts")
  .withReference(appDb)
  .waitFor(postgres);

await builder.build().run();

So if you’re attaching a durable volume to local Postgres, 13.2 handles it correctly out of the box. The PostgreSQL hosting docs show the same pattern in both TypeScript and C#.

That’s exactly the kind of solid platform support that keeps development moving.

🐛 Better debugging and fewer build paper cuts

13.2 also ships a set of quality-of-life improvements to day-to-day development, particularly around debugging and builds.

Better debugger displays

Core Aspire types now use DebuggerDisplayAttribute, so stepping through an AppHost is less of a scavenger hunt. You get clearer values for things like DistributedApplication, resources, and endpoint expressions instead of drilling into objects just to figure out what you’re looking at.

Better WaitFor failures and event behavior

When resources fail to start, the messages around WaitFor are more helpful. That’s good.

BeforeResourceStartedEvent also now fires only when a resource is actually starting, which is even better. Less noise. Better signal. More predictable behavior.

launchSettings.json is less fragile now

Aspire now accepts comments and trailing commas in launchSettings.json.

This is a welcome improvement. Real developers leave trailing commas and add comments to explain why a setting exists, and now Aspire handles that gracefully, just as you’d expect.

GenerateAssemblyInfo no longer gets in the way

If your AppHost disables GenerateAssemblyInfo, 13.2 now behaves correctly without requiring any workarounds. Another solid improvement to build reliability.

🌐 The bigger JavaScript picture

What I like about this release is that it keeps pushing the same idea forward: JavaScript support in Aspire isn’t a novelty feature.

This is what platform maturity looks like. Thoughtful, confident progress that makes polyglot development feel natural and productive.

If you’re using C# as the orchestration layer and JavaScript for the parts that are best written in JavaScript, Aspire keeps getting better at supporting you exactly where you are. That’s the goal.

🎉 The bottom line

Aspire 13.2 doesn’t reinvent the JavaScript story. It sharpens it.

Bun is now a first-class option for Vite apps. Yarn is more reliable. Containers are more predictable. Debugging is nicer. Build reliability is stronger. Each improvement is purposeful, and together they make the experience feel cohesive and polished.

That’s what great releases look like: consistent forward momentum, where the tooling does the right thing and development flows without interruption.

Get involved

Author

David Pine
Senior Software Engineer

David Pine is a Senior Software Engineer at Microsoft, leading UX and developer experience for aspire.dev. He is also a long-time community contributor, author, and speaker.

0 comments