| name | bun |
| description | Bun runtime: build fast Node.js-compatible APIs with Bun's built-in server, bundler, test runner, and package manager — Elysia framework, SQLite, and edge-optimised patterns |
Bun Skill
When to activate
- Building a new API or service with Bun as the runtime
- Using Elysia framework (the Hono/Express equivalent for Bun)
- Migrating a Node.js application to Bun for performance gains
- Using Bun's built-in SQLite for edge or embedded databases
- Setting up Bun's built-in test runner (no Jest needed)
When NOT to use
- Cloudflare Workers — use the hono skill (Bun runs on servers, not Cloudflare edge)
- Next.js projects — Next.js uses Node.js; Bun compatibility is improving but not complete
- Projects with native Node.js addons that don't support Bun yet
Instructions
Project setup
curl -fsSL https://bun.sh/install | bash
mkdir my-api && cd my-api
bun init
bun create elysia my-api
cd my-api && bun install
bun run index.ts
bun --watch index.ts
bun install
bun add express
bun remove express
bun update
Bun native HTTP server
Build a Bun HTTP server for [use case].
const server = Bun.serve({
port: 3000,
hostname: '0.0.0.0',
async fetch(req) {
const url = new URL(req.url)
if (url.pathname === '/health') {
return Response.json({ status: 'ok', uptime: process.uptime() })
}
if (url.pathname === '/api/users' && req.method === 'GET') {
const users = await getUsers()
return Response.json(users)
}
if (url.pathname === '/api/users' && req.method === 'POST') {
const body = await req.json()
const user = (body)
.(user, { : })
}
(, { : })
},
() {
.(error)
.({ : }, { : })
},
})
.()
Elysia framework
Build an Elysia API for [service].
Elysia is the idiomatic Bun web framework — type-safe, fast, minimal.
npm install elysia @elysiajs/swagger
import { Elysia, t } from 'elysia'
import { swagger } from '@elysiajs/swagger'
const app = new Elysia()
.use(swagger())
.get('/health', () => ({ status: 'ok' }))
.get('/users/:id', ({ params: { id } }) => {
return getUserById(id)
}, {
params: t.Object({ id: t.String() }),
response: t.Object({
id: t.String(),
name: t.String(),
email: t.String(),
})
})
.post(, ({ body }) => {
(body)
}, {
: t.({
: t.({ : }),
: t.({ : }),
})
})
.( {
auth = request..()
(!auth?.()) {
set. =
{ : }
}
})
.()
.()
the app my service.
Built-in SQLite
Use Bun's built-in SQLite for [use case].
// No installation needed — SQLite is built into Bun
import { Database } from 'bun:sqlite'
const db = new Database('myapp.db', { create: true })
// Create tables
db.run(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`)
// Prepared statements (fastest, prevents SQL injection)
const insertUser = db.prepare(
'INSERT INTO users (email, name) VALUES (?, ?) RETURNING *'
)
const getUser = db.prepare(
'SELECT * FROM users WHERE id = ?'
)
const listUsers = db.prepare(
'SELECT * FROM users ORDER BY created_at DESC LIMIT ? OFFSET ?'
)
// Execute
const newUser = insertUser.get('alice@example.com', 'Alice')
const user = getUser.get(1)
const users = listUsers.all(20, 0)
// Transactions (atomic operations)
const transferPoints = db.transaction((fromId: number, toId: number, points: number) => {
db.run('UPDATE users SET points = points - ? WHERE id = ?', [points, fromId])
db.run('UPDATE users SET points = points + ? WHERE id = ?', [points, toId])
})
transferPoints(1, 2, 100) // atomic — both or neither
// Close when done
db.close()
Bun test runner
Write tests for [module] using Bun's built-in test runner.
// No Jest, Vitest, or Mocha needed — Bun has a built-in runner
// Run: bun test
import { describe, it, expect, beforeAll, afterAll, mock } from 'bun:test'
import { createUser, getUser } from './users'
describe('User service', () => {
describe('createUser', () => {
it('creates a user and returns an ID', async () => {
const user = await createUser({ name: 'Alice', email: 'alice@example.com' })
expect(user.id).toBeString()
expect(user.name).toBe('Alice')
})
it('throws on duplicate email', async () => {
await createUser({ name: 'Bob', email: 'bob@example.com' })
expect(
createUser({ name: 'Bob 2', email: 'bob@example.com' })
).rejects.toThrow()
})
})
})
// Mock modules
const mockEmailService = mock(() => Promise.resolve({ id: 'email-123' }))
// Watch mode
// bun test --watch
// Coverage
// bun test --coverage
// Filter tests
// bun test --testNamePattern "createUser"
Performance benchmarks
bun run bench.ts
// bench.ts
const results = await fetch('http://localhost:3000/api/users')
console.time('100 requests')
for (let i = 0; i < 100; i++) {
await fetch('http://localhost:3000/api/users')
}
console.timeEnd('100 requests')
Example
User: I want to build a fast REST API for a weekend project. Should I use Bun + Elysia or Node.js + Hono?
Claude's comparison:
For a weekend project where you want speed of development AND runtime performance:
Use Bun + Elysia if:
- You want one runtime for everything (package manager, bundler, test runner, TypeScript — no config)
- You're on a Mac or Linux (Bun is fully supported; Windows support is improving)
- You want the fastest possible cold-start and throughput
- You like end-to-end type safety (Elysia's type inference is excellent)
Use Hono + Cloudflare Workers if:
- You want global edge deployment (Bun runs on VPS, not Cloudflare)
- You need Cloudflare's KV, D1, or R2
- You're already familiar with Hono's API
For a weekend project: Bun + Elysia wins — bun create elysia my-api has you running in 30 seconds with hot reload, built-in Swagger, and type-safe routes. No tsconfig tweaking, no jest config, no nodemon.
bun create elysia my-api && cd my-api && bun dev