Hono is a tiny, fast web framework built on Web Standards (the Request/Response API). Its headline feature is portability: the same router runs on Node, Bun, Deno, Cloudflare Workers, and more. That flexibility means your first deployment decision is *which runtime and adapter* you are targeting.
Pick a runtime adapter
Hono's core is runtime-agnostic, but the entry point differs per runtime:
| Runtime | Adapter / entry | Notes |
|---|---|---|
| Node.js | @hono/node-server | Most portable to container platforms |
| Bun | Bun.serve (built-in) | Fastest cold start, native fetch server |
| Deno | Deno.serve | Web-standard, good for Deno Deploy |
| Cloudflare Workers | export default app | Edge, but no long-lived TCP DB connections |
For a standard container deploy with a database, Node or Bun is the practical choice. I'll show Node since it is the most universal.
A Node-server Hono app
npm install hono @hono/node-server// src/index.ts
import { Hono } from 'hono';
import { serve } from '@hono/node-server';
const app = new Hono();
app.get('/health', (c) => c.json({ status: 'ok' }));
app.get('/api/users/:id', (c) => c.json({ id: c.req.param('id') }));
const port = Number(process.env.PORT ?? 3000);
serve({ fetch: app.fetch, port, hostname: '0.0.0.0' });
console.log(`listening on :${port}`);Binding to 0.0.0.0 (not localhost) is essential inside a container — the platform's proxy must reach it.
Build it
Hono apps are tiny. Compile TypeScript with tsc or bundle with esbuild for a single file:
npx esbuild src/index.ts --bundle --platform=node --target=node20 \
--outfile=dist/index.jsFROM node:20-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npx esbuild src/index.ts --bundle --platform=node --target=node20 --outfile=dist/index.js
FROM node:20-slim
WORKDIR /app
COPY --from=build /app/dist ./dist
ENV NODE_ENV=production
EXPOSE 3000
CMD ["node", "dist/index.js"]The resulting image is small and starts fast — which matters if you run on scale-to-zero infrastructure.
Adding a database
If your API talks to PostgreSQL, use a pooled client and read the URL from the environment:
import postgres from 'postgres';
const sql = postgres(process.env.DATABASE_URL, { max: 10 });
app.get('/api/posts', async (c) => {
const rows = await sql`SELECT * FROM posts LIMIT 20`;
return c.json(rows);
});Keep the pool modest. On serverless edge runtimes you would use an HTTP-based driver instead, but on a Node container a normal pooled TCP connection is correct and faster.
Deploying on PandaStack
A Node-server Hono app is just a container that listens on PORT:
- 1(Optional) Provision a managed PostgreSQL; PandaStack injects
DATABASE_URL. - 2Connect the Git repo as a container app. The Dockerfile is auto-detected; without one, the Node buildpack handles it.
- 3Set
NODE_ENV=production. The platform setsPORT; your code already reads it. - 4Add a custom domain; SSL provisions automatically.
If you target Bun instead, point the start command at bun run src/index.ts — PandaStack supports Bun as an install/runtime option, and Bun's fast startup pairs well with scale-to-zero.
Production notes
- Logging: add Hono's logger middleware (
import { logger } from 'hono/logger') so requests show up in live logs. - CORS: use
hono/corsand lock the origin list to your frontends. - Validation:
@hono/zod-validatorgives typed request validation with almost no overhead. - Cold starts: Hono's tiny footprint means cold starts are quick; still, for latency-critical APIs use always-on compute rather than scale-to-zero.
Verifying
curl -s https://api.example.com/health
# {"status":"ok"}If the health route answers and your data routes return rows, you are live.
References
- [Hono documentation](https://hono.dev/docs/)
- [Hono Node.js adapter](https://hono.dev/docs/getting-started/nodejs)
- [Hono Bun adapter](https://hono.dev/docs/getting-started/bun)
- [Hono middleware (logger, CORS)](https://hono.dev/docs/middleware/builtin/logger)
---
Hono's small, fast container is exactly what scale-to-zero infrastructure rewards — and PandaStack auto-detects Node or Bun and injects DATABASE_URL when you add a managed database. Try it free at [dashboard.pandastack.io](https://dashboard.pandastack.io).