Client Area

Modern Node.js APIs with Hono, Bun, and Edge Runtime

ByDomain India Team·DomainIndia Engineering
6 min read24 Apr 20263 views
# Modern Node.js APIs with Hono, Bun, and Edge Runtime
TL;DR
Node.js APIs in 2026 look different from Express. Hono (lightweight, multi-runtime), Bun (30× faster install, built-in APIs), and edge-compatible code let you run the same app on DomainIndia VPS, Cloudflare Workers, Vercel, or Deno Deploy. This guide shows a unified stack.
## The 2026 Node.js landscape
FrameworkYearRuntimePhilosophy
Express2010Node.js onlyMature, minimal, large ecosystem
Fastify2016Node.js2× faster than Express, schema-first
Koa2013Node.jsExpress successor by same team, async-native
Hono2022Node/Deno/Bun/EdgeMulti-runtime, Web-Fetch-API-based
ElysiaJS2023Bun onlyBun-native, type safety
**Pick Hono** for new greenfield APIs — it runs identically on Node.js (DomainIndia VPS), Bun, Deno, Cloudflare Workers, Vercel Functions, AWS Lambda. Deploy flexibility without code changes. ## Why Bun runtime
MetricNode.js 20Bun 1.1Deno 1.46
Install speedBaseline25-30× fasterSimilar to Node
Startup time~200ms~20ms~100ms
Built-in APIsRequires packagesBuilt-in (SQLite, WS, password hashing)Requires packages
Package mgmtnpm/yarn/pnpmbun install (lockfile-compatible)JSR / npm
Production-ready 2026?YesYesYes (for greenfield)
Bun wins for dev experience + install speed. Node.js is still the most proven in production. ## Step 1 — Install Bun on DomainIndia VPS ```bash curl -fsSL https://bun.sh/install | bash source ~/.bashrc bun --version ``` Or stick with Node.js 20+: ```bash # AlmaLinux sudo dnf install -y nodejs npm # Ubuntu curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash - sudo apt install -y nodejs ``` ## Step 2 — Scaffold Hono API ```bash mkdir myapi && cd myapi bun init # or: npm init -y bun add hono # or: npm install hono ``` `src/index.ts`: ```typescript import { Hono } from 'hono'; import { logger } from 'hono/logger'; import { cors } from 'hono/cors'; import { jwt } from 'hono/jwt'; import { zValidator } from '@hono/zod-validator'; import { z } from 'zod'; const app = new Hono(); app.use('*', logger()); app.use('*', cors({ origin: ['https://yourcompany.com'] })); // Public routes app.get('/health', (c) => c.json({ status: 'ok', version: '1.0.0' })); // Protected routes app.use('/v1/*', jwt({ secret: Bun.env.JWT_SECRET! })); const userSchema = z.object({ email: z.string().email(), name: z.string().min(1), }); app.post('/v1/users', zValidator('json', userSchema), async (c) => { const { email, name } = c.req.valid('json'); const user = await createUser(email, name); // your DB call return c.json(user, 201); }); app.get('/v1/users/:id', async (c) => { const user = await getUser(c.req.param('id')); if (!user) return c.json({ error: 'Not found' }, 404); return c.json(user); }); // Error handler app.onError((err, c) => { console.error(err); return c.json({ error: err.message }, 500); }); export default { port: Number(Bun.env.PORT) || 3000, fetch: app.fetch, }; ``` Run with Bun: ```bash bun run --watch src/index.ts ``` Or Node.js (via `@hono/node-server`): ```bash bun add @hono/node-server # src/server.ts: # import { serve } from '@hono/node-server'; # serve({ fetch: app.fetch, port: 3000 }); node src/server.ts ``` Same code. Swap runtime. ## Step 3 — Database with Bun's built-in SQLite or Drizzle **SQLite (Bun native, no dep):** ```typescript import { Database } from 'bun:sqlite'; const db = new Database('data.db', { create: true }); db.run(` CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, email TEXT UNIQUE, name TEXT ) `); const insertUser = db.prepare('INSERT INTO users (id, email, name) VALUES (?, ?, ?)'); insertUser.run(crypto.randomUUID(), '[email protected]', 'Rajesh'); const users = db.prepare('SELECT * FROM users').all(); ``` **PostgreSQL with Drizzle ORM (works everywhere):** ```bash bun add drizzle-orm postgres bun add -D drizzle-kit ``` ```typescript import { drizzle } from 'drizzle-orm/postgres-js'; import postgres from 'postgres'; import { pgTable, text, timestamp } from 'drizzle-orm/pg-core'; const client = postgres(Bun.env.DATABASE_URL!); export const db = drizzle(client); export const users = pgTable('users', { id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()), email: text('email').unique().notNull(), name: text('name').notNull(), createdAt: timestamp('created_at').defaultNow(), }); // Usage: await db.insert(users).values({ email: '[email protected]', name: 'Rajesh' }); const all = await db.select().from(users); ``` Drizzle is type-safe, introspectable, and works on Node, Bun, Edge. Unlike Prisma, no code generation step or binary dependency. ## Step 4 — Deploy to DomainIndia VPS systemd service `/etc/systemd/system/hono-api.service`: ```ini [Unit] Description=Hono API After=network.target postgresql.service [Service] Type=simple User=hono WorkingDirectory=/opt/hono-api ExecStart=/home/hono/.bun/bin/bun run src/index.ts Restart=on-failure RestartSec=3 EnvironmentFile=/opt/hono-api/.env StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target ``` Front with nginx + SSL (see [Go deployment guide](https://domainindia.com/support/kb/running-go-applications-vps-systemd-reverse-proxy) for same pattern). ## Step 5 — Deploy to Cloudflare Workers (same code!) The magic of Hono: deploy the same `app` to Cloudflare Workers: ```bash npm install -g wrangler wrangler init --yes ``` `wrangler.toml`: ```toml name = "hono-api" main = "src/index.ts" compatibility_date = "2026-04-01" ``` `src/index.ts` (modified for Workers): ```typescript export default { async fetch(request: Request, env: Env): Promise { return app.fetch(request, env); }, }; ``` Deploy: ```bash wrangler deploy ``` Same business logic. Now runs at 330+ edge locations. Dev/prod parity with your VPS. ## Pattern: Edge + origin Route some requests to edge (fast, cheap), others to VPS (stateful): ``` Client ─► Cloudflare Worker │ ├── /api/search → Worker handles (cached, fast) ├── /api/health → Worker handles └── /api/orders → Forwards to VPS (needs DB) ``` ```typescript app.get('/api/orders/*', async (c) => { // Forward to VPS origin return fetch(`https://origin.yourcompany.com${c.req.path}`, c.req.raw); }); ``` ## Performance — real numbers On a DomainIndia VPS Starter (2 GB):
StackReq/sec (hello world)Req/sec (DB query)
Express + Node.js 2018,0002,500
Hono + Node.js 2032,0003,000
Hono + Bun55,0003,200
Hono + Cloudflare Workers(global edge)(depends on origin)
Hono + Bun gives you raw throughput. For DB-bound workloads, runtime choice matters less — Postgres is the bottleneck. ## Testing Hono's test utility: ```typescript import { describe, test, expect } from 'bun:test'; describe('Health', () => { test('returns ok', async () => { const res = await app.request('/health'); expect(res.status).toBe(200); const body = await res.json(); expect(body.status).toBe('ok'); }); }); ``` Run: `bun test`. ## Common pitfalls ## FAQ
Q Hono, Express, or Fastify for new projects in 2026?

Hono — multi-runtime, future-proof, minimal. Express still fine for pure Node.js simplicity. Fastify if you need schema-first JSON validation and don't care about edge deployment.

Q Bun in production — is it ready?

Yes, for 2026. Major apps (Midjourney, Vercel, Supabase) use it. Node.js is still more battle-tested; go Bun for greenfield, Node for legacy.

Q Drizzle vs Prisma?

Drizzle: TypeScript-first, SQL-like API, no codegen, runs on edge. Prisma: More polished CLI, bigger ecosystem, slower on edge. Both are solid; Drizzle is the modern trend.

Q Can I run Bun on DomainIndia shared hosting?

Shared cPanel "Setup Node.js App" doesn't support Bun runtime. Use VPS, or use Node.js compatibility mode and deploy normally.

Q Hono on Cloudflare Workers — any limits?

Workers Free: 100K req/day, 10ms CPU, 128 MB. Workers Paid: 10M/mo, 50ms CPU. Past that: VPS with Hono + Node/Bun is unlimited (pay per VPS, not per request).

Run modern Node/Bun APIs on a DomainIndia VPS — zero platform tax. Get a VPS

Was this article helpful?

Your feedback helps us improve our documentation

Still need help? Submit a support ticket