Skip to Content
advanced-guidesBest Practices

Last Updated: 3/11/2026


Best Practices

Hono is flexible, but following these best practices will help you build better applications.

Avoid Controllers

Don’t create Ruby on Rails-like controllers:

// ❌ Avoid const booksList = (c: Context) => { return c.json('list books') } app.get('/books', booksList)

The issue: Path parameters can’t be inferred without complex generics.

// ❌ Avoid const bookPermalink = (c: Context) => { const id = c.req.param('id') // Can't infer type return c.json(`get ${id}`) }

Instead, write handlers inline:

// ✅ Recommended app.get('/books/:id', (c) => { const id = c.req.param('id') // Type is inferred! return c.json(`get ${id}`) })

Use Factory for Reusable Handlers

If you need reusable handlers, use factory.createHandlers():

import { createFactory } from 'hono/factory' import { logger } from 'hono/logger' const factory = createFactory() const middleware = factory.createMiddleware(async (c, next) => { c.set('foo', 'bar') await next() }) const handlers = factory.createHandlers(logger(), middleware, (c) => { return c.json(c.var.foo) }) app.get('/api', ...handlers)

Building Larger Applications

Use app.route() to organize your code:

authors.ts:

import { Hono } from 'hono' const app = new Hono() app.get('/', (c) => c.json('list authors')) app.post('/', (c) => c.json('create author', 201)) app.get('/:id', (c) => c.json(`get ${c.req.param('id')}`)) export default app

books.ts:

import { Hono } from 'hono' const app = new Hono() app.get('/', (c) => c.json('list books')) app.post('/', (c) => c.json('create book', 201)) app.get('/:id', (c) => c.json(`get ${c.req.param('id')}`)) export default app

index.ts:

import { Hono } from 'hono' import authors from './authors' import books from './books' const app = new Hono() app.route('/authors', authors) app.route('/books', books) export default app

With RPC

For type-safe RPC, chain your routes:

authors.ts:

import { Hono } from 'hono' const app = new Hono() .get('/', (c) => c.json('list authors')) .post('/', (c) => c.json('create author', 201)) .get('/:id', (c) => c.json(`get ${c.req.param('id')}`)) export default app export type AppType = typeof app

Client:

import type { AppType } from './authors' import { hc } from 'hono/client' const client = hc<AppType>('http://localhost') // Fully typed!

See RPC with larger applications for details.