type: decision
status: active
timestamp: 2026-06-23
tags: [decision, framework, hono, portability, serverless, multi-rail]

Hono framework — write once, deploy to all 4 serverless rails

Every API/Worker uses Hono. Same logic writes once, deploys everywhere \ logic compiles to CF Workers, Deno Deploy, AWS Lambda, and Render Node \u2014\ \ via 4 thin adapter shims (~10 LOC each). Removes per-rail rewrites when failover\ \ requires switching rails."

Hono — one app, 4 deployment targets

Why Hono

Each serverless rail uses a different request/response API:

RailHandler signature
CF Workersexport default { async fetch(req, env, ctx) {} } — Web Fetch Request → Response
Deno DeployDeno.serve(async (req) => {}) — Web Fetch Request → Response
AWS Lambdaexport const handler = async (event) => {} — AWS-shaped JSON event
Render (Node)app.get('/', (req, res) => {}) — Express-style req/res

If we wrote raw handlers per rail, swapping rails on failover would require rewriting every endpoint. Hono is a thin framework that normalizes all four into one Web-Fetch-style API, and provides adapter functions for the non-Fetch rails.

The pattern

import { Hono } from 'hono'

const app = new Hono()
app.get('/', (c) => c.text('ok'))
app.get('/api/data', async (c) => c.json({ hello: 'world' }))

// Workers (zero changes):
export default app

// Deno Deploy entrypoint:
// Deno.serve(app.fetch)

// AWS Lambda entrypoint (uses Function URL):
// import { handle } from 'hono/aws-lambda'
// export const handler = handle(app)

// Render / Node entrypoint:
// import { serve } from '@hono/node-server'
// serve({ fetch: app.fetch, port: 3000 })

Business logic in app is the same. Only the 1-line entrypoint differs per rail. Adapter shims are ~10 LOC each.

Bundle size

Hono is 14 KB minified, well under CF Workers’ 1 MB limit. Faster cold-start than Express on Node.

When to use raw handlers instead

For the family default: start with Hono. The 14 KB cost is paid back the first time we need to fail over to a different rail.

Existing knowledge

Already documented in architecture/api-umbrella-hono-worker.md (the Hono Worker that fronts all our APIs at api.oriz.in). This decision extends it: ALL new Workers + functions use Hono, not just the umbrella.

Cross-refs


Edit on GitHub · Back to index