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
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Create a new project
mkdir my-api && cd my-api
bun init # creates package.json, index.ts, tsconfig.json
# Or scaffold with Elysia
bun create elysia my-api
cd my-api && bun install
# Run
bun run index.ts # or: bun index.ts
bun --watch index.ts # hot reload
# Package management (drop-in npm replacement, 10-100x faster)
bun install # install from package.json
bun add express # add a package
bun remove express # remove a package
bun update # update all
Bun native HTTP server
Build a Bun HTTP server for [use case].
// index.ts — Bun's built-in server (no framework needed for simple APIs)
const server = Bun.serve({
port: 3000,
hostname: '0.0.0.0',
async fetch(req) {
const url = new URL(req.url)
// Route handling
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 = await createUser(body)
return Response.json(user, { status: 201 })
}
return new Response('Not Found', { status: 404 })
},
error(error) {
console.error(error)
return Response.json({ error: 'Internal server error' }, { status: 500 })
},
})
console.log(`Listening on http://localhost:${server.port}`)
Elysia framework
Build an Elysia API for [service].
Elysia is the idiomatic Bun web framework — type-safe, fast, minimal.
npm install elysia @elysiajs/swagger
// app.ts
import { Elysia, t } from 'elysia'
import { swagger } from '@elysiajs/swagger'
const app = new Elysia()
.use(swagger()) // auto-generates Swagger UI at /swagger
// Define routes with full type safety
.get('/health', () => ({ status: 'ok' }))
// Route with path parameter
.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(),
})
})
// Route with body validation
.post('/users', async ({ body }) => {
return createUser(body)
}, {
body: t.Object({
name: t.String({ minLength: 1 }),
email: t.String({ format: 'email' }),
})
})
// Middleware (apply to all routes)
.onBeforeHandle(({ request, set }) => {
const auth = request.headers.get('Authorization')
if (!auth?.startsWith('Bearer ')) {
set.status = 401
return { error: 'Unauthorized' }
}
})
.listen(3000)
console.log(`Running at ${app.server?.hostname}:${app.server?.port}`)
Generate the Elysia app for 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 vs Node.js comparison for common tasks:
# Package install: bun install is ~10-30x faster than npm install
# TypeScript execution: bun runs .ts directly, no compilation step
# Startup time: ~3-5ms vs ~30-50ms for Node.js
# HTTP throughput: typically 2-3x more req/s than Express on Node.js
# Benchmark your Bun server:
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
# Running at http://localhost:3000 — that's it