Build High-Performance REST APIs with Bun in 2026
Source: Dev.to
Introduction
JavaScript runtimes have evolved rapidly. While Node.js dominated for over a decade, 2025‑2026 saw a massive shift toward Bun for high‑performance backend development. As of February 2026, Bun is a serious alternative to Node.js, especially for building REST APIs.
Why Choose Bun?
- Blazingly fast startup – starts significantly quicker than Node.js.
- Native APIs –
Bun.servereplaces Express‑like patterns with a built‑in, high‑performance server. - Built‑in database support – native SQLite and SQL support, no heavy ORM drivers needed.
- Zero dependencies – you can build entire APIs without installing any npm packages.
Prerequisites
curl -fsSL https://bun.sh/install | bash
Project Setup
mkdir bun-api-tutorial
cd bun-api-tutorial
bun init
Server Implementation
Create a file named server.ts and add the following code:
import { BunSQLite } from "bun:sqlite";
// 1. Initialize Database
const db = new BunSQLite("todos.db");
// Create table if not exists
db.query(`
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task TEXT NOT NULL,
completed INTEGER DEFAULT 0
)
`).run();
// 2. Configure the Server
const server = Bun.serve({
port: 3000,
async fetch(req) {
const url = new URL(req.url);
const method = req.method;
// Simple Router Logic
if (url.pathname === "/todos" && method === "GET") {
// GET /todos
const todos = db.query("SELECT * FROM todos").all();
return new Response(JSON.stringify(todos), {
headers: { "Content-Type": "application/json" }
});
}
if (url.pathname === "/todos" && method === "POST") {
// POST /todos
const { task } = await req.json();
if (!task) {
return new Response(JSON.stringify({ error: "Task is required" }), { status: 400 });
}
const info = db.query("INSERT INTO todos (task) VALUES (?)").run(task);
const newTodo = db.query("SELECT * FROM todos WHERE id = ?").get(info.lastInsertRowid);
return new Response(JSON.stringify(newTodo), {
headers: { "Content-Type": "application/json" },
status: 201
});
}
if (url.pathname.startsWith("/todos/") && method === "PUT") {
// PUT /todos/:id
const id = url.pathname.split("/")[2];
const { completed } = await req.json();
db.query("UPDATE todos SET completed = ? WHERE id = ?").run(completed ? 1 : 0, id);
const updated = db.query("SELECT * FROM todos WHERE id = ?").get(id);
return new Response(JSON.stringify(updated), {
headers: { "Content-Type": "application/json" }
});
}
if (url.pathname.startsWith("/todos/") && method === "DELETE") {
// DELETE /todos/:id
const id = url.pathname.split("/")[2];
db.query("DELETE FROM todos WHERE id = ?").run(id);
return new Response(JSON.stringify({ message: "Deleted" }), { status: 204 });
}
return new Response("Not Found", { status: 404 });
}
});
console.log(`Server running at http://localhost:${server.port}`);
BunSQLiteprovides a built‑in interface to SQLite with no external drivers.Bun.servehandles HTTP requests natively using the Web APIRequestandResponseobjects, eliminating the need for frameworks like Express or Fastify.
Running the Server
bun run server.ts
You should see:
Server running at http://localhost:3000
Testing the API
Create a Todo
curl -X POST http://localhost:3000/todos \
-H "Content-Type: application/json" \
-d '{"task": "Learn Bun in 2026"}'
List Todos
curl http://localhost:3000/todos
Performance Note
In benchmarks, Bun handles simple JSON APIs 2–3× faster than Node.js in I/O operations and uses considerably less memory. This makes Bun a production‑ready runtime for high‑performance services.
Conclusion
Bun is no longer just an experiment; it simplifies the backend stack by removing external HTTP frameworks and database drivers. Convert your next Node.js microservice to Bun and experience the speed difference yourself!