Bun is a JavaScript runtime built on JavaScriptCore, with a bundler, test runner, and package manager built in. As of Bun 1.4 it runs most NestJS apps unmodified, install times drop sharply, and request throughput on I/O-heavy endpoints is meaningfully higher.
What Works
bun installreads the samepackage.json, producesbun.lockb, and is an order of magnitude faster on a cold cache- Running the app:
bun run start:devworks with no code changes on a CLI-generated project - TypeScript execution: Bun runs
.tsdirectly, sots-nodeis no longer needed for seed and migration scripts @nestjs/platform-expressand@nestjs/platform-fastifyboth boot
What Doesn't (Yet)
- Native addons with a
binding.gypcan fail to load — check anything doing image processing, crypto, or native DB drivers @nestjs/testingstill pulls in Jest;bun testis not a drop-in replacement for the full Nest testing setup- A few Express middleware packages assume Node internals and throw at startup
Dockerfile
FROM oven/bun:1-alpine
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY . .
RUN bun run build
USER bun
CMD ["bun", "dist/main.js"]
The resulting image is roughly 25–40% smaller than the Node equivalent and starts faster.
Where the Win Is
The gains show up in process startup and I/O-bound request handling — API gateways, proxies, endpoints that mostly wait on a database. CPU-bound work sees little difference. Benchmark the endpoints that actually matter for your service before committing.
Conclusion
For a standard NestJS REST API, moving to Bun is mostly a CI and Dockerfile change. Run it on a lower-stakes service first and validate every native dependency.