Elysia is a TypeScript web framework designed specifically for Bun, leveraging Bun is native HTTP server for exceptional performance. It provides end-to-end type safety, automatic OpenAPI documentation, and a plugin ecosystem. This guide covers building and deploying Elysia applications on a VPS.
Project Setup
# Install Bun
curl -fsSL https://bun.sh/install | bash
# Create Elysia project
bun create elysia my-api
cd my-api
# Or manually
mkdir elysia-api && cd elysia-api
bun init
bun add elysia @elysiajs/cors @elysiajs/swagger
Application Code
// src/index.ts
import { Elysia, t } from "elysia";
import { cors } from "@elysiajs/cors";
import { swagger } from "@elysiajs/swagger";
const app = new Elysia()
.use(cors())
.use(swagger({
documentation: {
info: { title: "My API", version: "1.0.0" }
}
}))
.get("/health", () => ({ status: "healthy" }))
.group("/api", (app) =>
app
.get("/users", () => {
return [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
];
})
.post(
"/users",
({ body }) => {
return { id: 3, ...body };
},
{
body: t.Object({
name: t.String({ minLength: 2 }),
email: t.String({ format: "email" }),
}),
response: t.Object({
id: t.Number(),
name: t.String(),
email: t.String(),
}),
}
)
.get(
"/users/:id",
({ params: { id } }) => {
return { id: parseInt(id), name: "Alice", email: "alice@example.com" };
},
{
params: t.Object({ id: t.String() }),
}
)
)
.listen(process.env.PORT ?? 3000);
console.log(`Server running at ${app.server?.url}`);
Database Integration
// With Drizzle ORM (works great with Bun)
bun add drizzle-orm postgres
bun add -d drizzle-kit
// src/db/schema.ts
import { pgTable, serial, varchar, timestamp } from "drizzle-orm/pg-core";
export const users = pgTable("users", {
id: serial("id").primaryKey(),
name: varchar("name", { length: 100 }).notNull(),
email: varchar("email", { length: 255 }).notNull().unique(),
createdAt: timestamp("created_at").defaultNow(),
});
// src/db/index.ts
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
const client = postgres(process.env.DATABASE_URL!);
export const db = drizzle(client);
// In routes
import { db } from "./db";
import { users } from "./db/schema";
import { eq } from "drizzle-orm";
app.get("/api/users", async () => {
return await db.select().from(users);
});
Eden Treaty (Type-Safe Client)
// Elysia generates a type-safe client automatically
// Client code
import { treaty } from "@elysiajs/eden";
import type { App } from "../server";
const api = treaty<App>("http://localhost:3000");
// Fully typed!
const { data, error } = await api.api.users.get();
// data is typed as Array
const { data: newUser } = await api.api.users.post({
name: "Charlie",
email: "charlie@example.com",
});
// Compile-time validation of request body
Deployment
# Build (Bun compiles to a single executable)
bun build --compile --minify src/index.ts --outfile server
# Or run directly (Bun starts in milliseconds)
bun run src/index.ts
Docker Deployment
FROM oven/bun:1 AS builder
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile --production
COPY . .
FROM oven/bun:1-slim
WORKDIR /app
COPY --from=builder /app .
USER bun
EXPOSE 3000
CMD ["bun", "run", "src/index.ts"]
Systemd Service
[Unit]
Description=Elysia API
After=network.target
[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/elysia-api
ExecStart=/usr/local/bin/bun run src/index.ts
EnvironmentFile=/opt/elysia-api/.env
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
Performance
# Elysia on Bun benchmarks:
# Simple JSON: ~150,000 req/s (single core)
# With validation: ~120,000 req/s
# With DB query: ~40,000 req/s
# Comparison:
# Express (Node.js): ~15,000 req/s
# Fastify (Node.js): ~45,000 req/s
# Hono (Bun): ~120,000 req/s
Summary
Elysia on Bun represents the fastest TypeScript web framework available, combining Bun is native speed with end-to-end type safety. The Eden Treaty client eliminates API integration errors at compile time. Automatic Swagger documentation, validation via TypeBox, and a growing plugin ecosystem make it production-ready. For new TypeScript API projects where performance matters, the Bun + Elysia combination is the current best-in-class choice.