Step-by-Step: Migrating from Node.js 21 to Bun 1.2 for Your Backend APIs

Published: (May 3, 2026 at 03:20 PM EDT)
4 min read
Source: Dev.to

Source: Dev.to

Why Migrate to Bun 1.2?

Bun 1.2 is a modern JavaScript runtime built for speed, offering native TypeScript support, a built‑in bundler, test runner, and package manager. Compared to Node.js 21, Bun delivers up to 3× faster startup times, lower memory usage, and seamless compatibility with most Node.js APIs. For backend APIs, this translates to reduced infrastructure costs, faster response times, and simpler tooling.

Pre‑migration checklist

  • Audit all dependencies – use bun audit or consult the Bun Node.js Compatibility page to confirm support for critical packages.
  • Back up your project – create a separate Git branch or snapshot to revert if needed.
  • Identify Node‑specific implementations – look for uses of __dirname, __filename, or custom core‑module polyfills that may need adjustment.

Install Bun

curl -fsSL https://bun.sh/install | bash

Verify the installation:

bun --version
# Should output 1.2.x

Configure the project

Navigate to your existing Node.js 21 project directory. If you don’t have a bunfig.toml file, create one to customize Bun’s behavior:

# bunfig.toml
[install]
registry = "https://registry.npmjs.org"

[test]
preload = ["./test/setup.ts"]

Update package.json to set the project type to ESM (Bun works with CommonJS, but ESM is preferred for better compatibility):

{
  "type": "module",
  "scripts": {
    "start": "bun run src/index.ts",
    "test": "bun test"
  }
}

Replace npm install with Bun’s built‑in package manager:

bun install

Bun will read your existing package.json and lockfile (package-lock.json / yarn.lock) and generate a binary bun.lockb. If any dependencies throw errors, look for Bun‑compatible alternatives or update to the latest version.

Code adjustments

Switch from CommonJS to ESM

// Before (CommonJS)
const express = require("express");
const { PORT } = require("./config");

// After (ESM)
import express from "express";
import { PORT } from "./config.js"; // note the .js extension

Replace __dirname / __filename

// Before (Node.js CJS)
console.log(__dirname);

// After (Bun ESM)
import { fileURLToPath } from "url";
import { dirname } from "path";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

Environment variables

// Bun’s alias (slightly faster)
const port = Bun.env.PORT || 3000;

Optional: Use Bun‑optimized frameworks

If you’re using Express, it works fine, but you can switch to a Bun‑native framework like Elysia for extra performance:

import { Elysia } from "elysia";

const app = new Elysia()
  .get("/", () => "Hello from Bun 1.2!")
  .listen(3000, () => {
    console.log("Server running on port 3000");
  });

ORMs

For Prisma, Drizzle, or other ORMs, update the database connection to use Bun‑compatible drivers (e.g., bun:sqlite for SQLite, or standard PostgreSQL/MySQL drivers that work with Bun).

Testing with Bun

Bun includes a built‑in test runner compatible with Jest syntax.

# Run all tests
bun test

# Run a specific test file
bun test src/__tests__/api.test.ts

Validate API endpoints manually:

curl http://localhost:3000/api/users

Run your full integration test suite to confirm no regressions.

  • Use Bun.serve() for HTTP servers instead of http.createServer() when not using a framework.
  • Use Bun.file() and Bun.write() for file operations instead of the fs module polyfills.
  • Remove unnecessary Node shims (e.g., node-fetch is redundant because Bun has a built‑in fetch API).

Deploy with Bun 1.2

Docker

FROM oven/bun:1.2
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install
COPY . .
EXPOSE 3000
CMD ["bun", "run", "src/index.ts"]

Cloud providers

Bun is supported on platforms such as Fly.io, Railway, and Render. Follow each provider’s documentation to enable the Bun runtime.

CI/CD

Update your CI pipelines (GitHub Actions, GitLab CI, etc.) to install Bun instead of Node.js 21 before running build and test steps.

Common Pitfalls to Avoid

  • Forgetting to set "type": "module" in package.json when migrating to ESM.
  • Using Node core modules that are not yet supported in Bun (check the compatibility docs first).
  • Skipping thorough testing – always validate in a staging environment before rolling out to production.

Migrating from Node.js 21 to Bun 1.2 is straightforward for most backend APIs, with minimal code changes required. You’ll gain faster performance, simpler tooling, and access to Bun’s growing ecosystem of native tools. Start with a small, non‑critical API to test the process, then roll out to larger services once you’re comfortable with the workflow.

0 views
Back to Blog

Related posts

Read more »