Bun Runtime with Nuxt 4

Bun promises faster installs, native TypeScript, and better performance. Nuxt 4 supports it. But the reality is more nuanced.

The Promise

Bun offers significant improvements over Node.js:

  1. 4x faster package installs — Native resolver, no intermediate steps
  2. Native TypeScript — No transpilation required
  3. Faster HTTP — Up to 2.8x more requests per second
  4. Single binary — Runtime, bundler, package manager in one

Current Status

Nuxt officially supports Bun since version 3.6. Nuxt 4 continues this support through Nitro's Bun preset.

The catch: support does not mean parity. Several edge cases break.

[email protected] with [email protected]

Latest stable as of January 2026. Bun joined Anthropic in December 2025 — expect tighter integration with AI tooling.

Avoid Bun 1.2.14 through 1.2.20. Socket connection errors plague these versions with Nuxt.

Note: Nuxt 3 reaches end of maintenance at the end of January 2026. Migrate to Nuxt 4 if you haven't already.

Configuration

Basic Setup

Initialize a new project:

bunx nuxi init my-app
cd my-app
bun install

Development

Two modes exist:

# Uses Node.js runtime (default)
bun run dev

# Uses Bun runtime
bun --bun run dev

The --bun flag forces the Bun runtime. Without it, the Nuxt CLI falls back to Node.js.

Production Build

Configure the Nitro preset in nuxt.config.ts:

export default defineNuxtConfig({
  compatibilityDate: '2025-01-14',

  nitro: {
    preset: 'bun'
  }
})

Or set via environment variable:

NITRO_PRESET=bun bun run build

Why the Preset Matters

The default node-server preset does not bundle Bun-specific exports. If your app uses packages with Bun-specific features (like bun:sqlite), production builds break without the Bun preset.

Known Issues

Socket Errors on Windows

ENOENT: no such file or directory, listen '\\.\pipe\nuxt-dev-XXXX.sock'

Bun 1.2.14–1.2.20 fails on Windows with Nuxt 4. The workaround: use WSL.

HMR Breaks with Bun Runtime

When using bun --bun run dev, WebSocket connections fail:

WebSocket connection to 'ws://localhost:24678/_nuxt/' failed
[vite] server connection lost

Fix by enabling polling:

// nuxt.config.ts
export default defineNuxtConfig({
  vite: {
    server: {
      watch: {
        usePolling: true,
        interval: 100
      }
    }
  }
})

400 Errors on Non-GET Requests

All POST, PUT, DELETE requests return 400 in dev mode when using the Bun runtime or preset.

This only affects development. Production builds work correctly.

fsevents Crashes on macOS

Assertion failed: function fse_dispatch_event, file fsevents.c, line 151

Affects macOS with Nuxt 3.16.0+ and Bun 1.2.4+. Workaround: run without the --bun flag.

Memory Leak in Dev Mode

When running nuxt dev with compatibilityVersion: 4, memory usage climbs steadily. Starts at ~500MB, reaches 6GB after 5 minutes.

Only affects Bun runtime in development. Production builds and Node.js runtime work fine.

Tracked in GitHub Issue #16219.

crossws Module Error

RollupError: This module cannot be imported in server runtime.
[importing crossws/dist/adapters/bun.mjs]

Add to your config:

export default defineNuxtConfig({
  nitro: {
    preset: 'bun',
    rollupConfig: {
      external: ['bun']
    }
  }
})

Bun SQLite

Bun ships with a native SQLite driver via bun:sqlite. Zero dependencies, fast, and built-in.

Using bun:sqlite in Server Routes

// server/api/users.get.ts
import { Database } from 'bun:sqlite'

const db = new Database('mydb.sqlite')

export default defineEventHandler(() => {
  return db.query('SELECT * FROM users').all()
})

The Catch

This only works when:

  1. Running with Bun runtime (bun --bun run dev or production with Bun preset)
  2. Building with nitro.preset: 'bun'

Without the Bun preset, production builds use Node.js and bun:sqlite imports fail.

Configuration for bun:sqlite

// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    preset: 'bun',
    rollupConfig: {
      external: ['bun:sqlite']
    }
  }
})

Nuxt Content and SQLite

Nuxt Content v3 uses SQLite internally. This creates friction with Bun.

The Problem

Nuxt Content depends on better-sqlite3 for Node.js. This native module doesn't compile for Bun — different ABI versions.

Error: The module 'better_sqlite3' was compiled against a different Node.js ABI version

Current Status

Nuxt Content should auto-detect Bun and use bun:sqlite instead of better-sqlite3. In practice, detection fails in some scenarios.

Tracked in GitHub Issue #2936 and Issue #3118.

Workarounds

Option 1: Install with npm, run with Bun

npm install
bun run dev

This bypasses the better-sqlite3 compilation issue during install.

Option 2: Use Node.js native SQLite (v22.5+)

If you're on Node.js 22.5+, enable experimental native SQLite:

// nuxt.config.ts
export default defineNuxtConfig({
  content: {
    experimental: {
      nativeSqlite: true
    }
  }
})

Option 3: Skip Nuxt Content for Bun projects

If you need full Bun runtime in production, consider alternatives:

  • Static markdown with @nuxt/content in prerender mode
  • Custom markdown parsing with marked or remark
  • External CMS (Strapi, Sanity, Contentful)

Production Builds

Nuxt Content works in production builds if you prerender content at build time. The SQLite database gets bundled into the output.

// nuxt.config.ts
export default defineNuxtConfig({
  content: {
    database: {
      type: 'sqlite',
      filename: ':memory:'
    }
  },
  routeRules: {
    '/blog/**': { prerender: true }
  }
})

Module Compatibility

Some Nuxt modules have known issues with Bun:

ModuleIssue
@nuxt/contentbetter-sqlite3 ABI mismatch
@prisma/nuxtFreezes during client generation
@nuxtjs/storybookFails to detect Bun as package manager
nuxt-modules/supabaseInstallation errors
wrangler/nitro-cloudflare-devFails with Bun

Prisma Workaround

Delete bun.lockb before first dev run:

rm bun.lockb
bun install
bun run dev

Performance Reality

Benchmarks Look Great

MetricBunNode.jsImprovement
HTTP Requests/sec~180,000~65,0002.8x
Package Install4.2x fasterBaseline4.2x
TypeScript Transpile2.8x fasterBaseline2.8x

Production Reality

Hello-world benchmarks show dramatic improvements. Standard CRUD operations show comparable performance.

Cold-start time in serverless can be higher for Bun. Memory usage may increase in some scenarios.

Test your actual workload. Benchmarks lie.

When to Use Bun

Good Candidates

  • Greenfield projects — Native TypeScript, faster feedback
  • Side projects — Speed compounds when iterating
  • CI/CD pipelines — 4x faster package installs matter
  • Serverless deployments — Lower cold-start latency

Stick with Node.js

  • Large enterprise codebases — Migration rarely pays off
  • Heavy native module usage — Better compatibility
  • Windows development — Known socket issues
  • Maximum stability required — Node.js has decades of battle-testing

Production Checklist

Before Deployment

  1. Lock Bun version in package.json:
{
  "packageManager": "[email protected]"
}
  1. Test all HTTP methods work
  2. Build locally first — NITRO_PRESET=bun bun run build
  3. Run the production build — bun run .output/server/index.mjs

Docker Configuration

# Build Stage
FROM oven/bun:1-alpine AS build
WORKDIR /app
COPY package.json bun.lock* ./
RUN bun install --frozen-lockfile --ignore-scripts
COPY . .
ENV NITRO_PRESET=bun
RUN bun run build

# Production Stage
FROM oven/bun:1-alpine AS production
WORKDIR /app
RUN addgroup --system --gid 1001 nuxt \
    && adduser --system --uid 1001 nuxt
COPY --from=build --chown=nuxt:nuxt /app/.output ./.output
USER nuxt
ENV HOST=0.0.0.0
ENV PORT=3000
EXPOSE 3000
CMD ["bun", "--bun", "run", ".output/server/index.mjs"]

Environment Variables

VariableDescription
PORT or NITRO_PORTServer port (default: 3000)
HOST or NITRO_HOSTServer host (default: 0.0.0.0)

Note: NITRO_HOST may not work with the Bun preset. Only NITRO_PORT is reliable.

Testing Setup

Vitest Configuration

// vitest.config.ts
import { defineVitestConfig } from '@nuxt/test-utils/config'

export default defineVitestConfig({
  test: {
    environment: 'nuxt',
    environmentOptions: {
      nuxt: {
        domEnvironment: 'happy-dom'
      }
    }
  }
})

Running Tests

bun run test
bun run test:e2e

Practical Recommendation

Use Bun as a package manager. Run development with Node.js. Deploy production with the Bun preset.

# Install with Bun (fast)
bun install

# Develop with Node.js (stable)
bun run dev

# Build for Bun runtime
NITRO_PRESET=bun bun run build

# Run production
bun run .output/server/index.mjs

This approach gives you faster installs without the development instability.

Summary

Bun with Nuxt 4 works. It is not seamless.

  1. Use Bun 1.3.6 with Nuxt 4.2.2 (latest stable)
  2. Set nitro.preset: 'bun' for production
  3. Avoid --bun flag in development if you hit issues
  4. Test all HTTP methods before deploying
  5. Use WSL on Windows
  6. Watch for memory leaks in long dev sessions

The performance gains are real. The edge cases are also real. Know both before committing.

References

Nuxt 4 Documentation

nuxt.com — Official installation and deployment guides

Bun + Nuxt Guide

bun.com — Official Bun documentation for Nuxt

Nitro Bun Runtime

nitro.build — Nitro preset documentation

GitHub Issue #32875

github.com — Unable to run Nuxt 4 on Bun tracking issue

GitHub Issue #21762

github.com — Bun version compatibility tracking

GitHub Issue #16219

github.com — Memory leak in dev mode

GitHub Issue #31249

github.com — HMR breaks with Bun runtime

GitHub Issue #2936

github.com — Nuxt Content better-sqlite3 doesn't work with Bun

GitHub Issue #3118

github.com — bunsqlite polyfills regression