Step-by-Step: Migrating from Node.js 21 to Bun 1.2 for Your Backend APIs
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 auditor 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.
Replace Node‑specific APIs (optional but recommended)
- Use
Bun.serve()for HTTP servers instead ofhttp.createServer()when not using a framework. - Use
Bun.file()andBun.write()for file operations instead of thefsmodule polyfills. - Remove unnecessary Node shims (e.g.,
node-fetchis redundant because Bun has a built‑infetchAPI).
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"inpackage.jsonwhen 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.