Overview
Deploy Hono on Bun with native Bun.serve(). Best for high-performance applications using Bun.
Features
- Native Bun.serve() for maximum performance
- Security headers and CORS
- Structured JSON logging
- Health, ready, and live endpoints
- Graceful shutdown
- Memory and uptime reporting
Installation
npx hanma add hono-bun --framework hono
Dependencies
hono
Code
import { Hono } from "hono";
import { logger } from "hono/logger";
import { requestId } from "hono/request-id";
import { cors } from "hono/cors";
import { secureHeaders } from "hono/secure-headers";
import { timing } from "hono/timing";
import type { Context } from "hono";
// Environment configuration
const config = {
port: Number(Bun.env.PORT) || 3000,
env: Bun.env.NODE_ENV || "development",
corsOrigins: Bun.env.CORS_ORIGINS?.split(",") || ["*"],
};
// Application type with custom variables
type AppEnv = {
Variables: {
requestId: string;
startTime: number;
};
};
const app = new Hono<AppEnv>();
// Security and observability middleware
app.use("*", secureHeaders());
app.use("*", timing());
app.use("*", requestId());
app.use("*", logger());
app.use("*", cors({
origin: config.corsOrigins,
allowMethods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
allowHeaders: ["Content-Type", "Authorization", "X-Request-ID"],
exposeHeaders: ["X-Request-ID", "X-Response-Time"],
maxAge: 86400,
credentials: true,
}));
// Request timing middleware
app.use("*", async (c, next) => {
c.set("startTime", Date.now());
await next();
});
// Health check endpoint
app.get("/health", (c) => {
const uptime = process.uptime();
const memory = process.memoryUsage();
return c.json({
status: "healthy",
timestamp: new Date().toISOString(),
runtime: "bun",
version: Bun.version,
uptime: {
seconds: Math.floor(uptime),
formatted: formatUptime(uptime),
},
memory: {
heapUsed: formatBytes(memory.heapUsed),
heapTotal: formatBytes(memory.heapTotal),
rss: formatBytes(memory.rss),
},
});
});
// Readiness check for k8s/container orchestration
app.get("/ready", (c) => {
// Add your readiness checks here (DB connection, cache, etc.)
return c.json({ ready: true });
});
// Liveness check
app.get("/live", (c) => c.text("OK"));
// Example route
app.get("/", (c) => {
return c.json({
message: "Hello from Bun!",
requestId: c.get("requestId"),
environment: config.env,
});
});
// 404 handler
app.notFound((c) => {
return c.json(
{
success: false,
error: {
code: "NOT_FOUND",
message: `Path ${c.req.method} ${c.req.path} not found`,
},
requestId: c.get("requestId"),
},
404
);
});
// Global error handler
app.onError((err, c) => {
const requestId = c.get("requestId") || "unknown";
const status = "status" in err ? (err.status as number) : 500;
// Log error with context
console.error(JSON.stringify({
level: "error",
message: err.message,
stack: err.stack,
requestId,
path: c.req.path,
method: c.req.method,
timestamp: new Date().toISOString(),
}));
return c.json(
{
success: false,
error: {
code: status === 500 ? "INTERNAL_ERROR" : "REQUEST_ERROR",
message: config.env === "production"
? "An unexpected error occurred"
: err.message,
},
requestId,
},
status
);
});
// Utility functions
function formatUptime(seconds: number): string {
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
const mins = Math.floor((seconds % 3600) / 60);
return `${days}d ${hours}h ${mins}m`;
}
function formatBytes(bytes: number): string {
const units = ["B", "KB", "MB", "GB"];
let i = 0;
while (bytes >= 1024 && i < units.length - 1) {
bytes /= 1024;
i++;
}
return `${bytes.toFixed(2)} ${units[i]}`;
}
// Server instance
let server: ReturnType<typeof Bun.serve> | null = null;
// Start server
export const startServer = () => {
if (server) {
console.log("Server already running");
return;
}
server = Bun.serve({
port: config.port,
fetch: app.fetch,
error(error) {
console.error("Unhandled server error:", error);
return new Response("Internal Server Error", { status: 500 });
},
});
console.log(`Hono running on http://localhost:${server.port}`);
};
// Graceful shutdown
let isShuttingDown = false;
export const shutdown = (signal: string) => {
if (isShuttingDown || !server) return;
isShuttingDown = true;
console.log(`${signal} received. Shutting down...`);
server.stop();
console.log("Server stopped");
process.exit(0);
};
Usage
// Run with: bun run src/index.ts
// Health check: GET /health
Dependencies
hono
Frequently Asked Questions
How do I install Bun Server?
Run the following command:
npx hanma add hono-bun --framework honoWhat dependencies are required?
This snippet requires: hono. Make sure to install them before using the snippet.
How do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to
src/index.ts.Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.