What is Middleware?
Middleware is a function that runs before your route handler. It can modify the request, response, or perform side effects like logging, authentication, or error handling. Middleware functions have access to the context object and a next() function to pass control to the next middleware or route handler.
Middleware Execution Flow
Middleware executes in the order it’s registered:
const app = new Hono ()
app . use ( '*' , async ( c , next ) => {
console . log ( '1. First middleware - before' )
await next ()
console . log ( '1. First middleware - after' )
})
app . use ( '*' , async ( c , next ) => {
console . log ( '2. Second middleware - before' )
await next ()
console . log ( '2. Second middleware - after' )
})
app . get ( '/hello' , ( c ) => {
console . log ( '3. Route handler' )
return c . text ( 'Hello!' )
})
// Request to /hello outputs:
// 1. First middleware - before
// 2. Second middleware - before
// 3. Route handler
// 2. Second middleware - after
// 1. First middleware - after
This “onion model” allows middleware to execute code both before and after the route handler.
Using Middleware with app.use()
The app.use() method registers middleware. It can be used in several ways:
Global Middleware
Apply middleware to all routes:
import { Hono } from 'hono'
import { logger } from 'hono/logger'
const app = new Hono ()
// Applies to all routes
app . use ( logger ())
app . get ( '/' , ( c ) => c . text ( 'Home' ))
app . get ( '/about' , ( c ) => c . text ( 'About' ))
Route-Specific Middleware
Apply middleware to specific routes or paths:
import { Hono } from 'hono'
import { jwt } from 'hono/jwt'
import { cors } from 'hono/cors'
const app = new Hono ()
// Applies to /api/* routes
app . use ( '/api/*' , cors ())
// Applies to /auth/* routes
app . use ( '/auth/*' , jwt ({ secret: 'secret-key' , alg: 'HS256' }))
app . get ( '/api/posts' , ( c ) => c . json ({ posts: [] }))
app . get ( '/auth/profile' , ( c ) => c . json ({ user: 'John' }))
app . get ( '/public' , ( c ) => c . text ( 'Public page' )) // No middleware
Multiple Middleware
Chain multiple middleware together:
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
import { jwt } from 'hono/jwt'
const app = new Hono ()
// Multiple middleware in one call
app . use ( '/api/*' , logger (), cors (), jwt ({ secret: 'secret' , alg: 'HS256' }))
// Or chain them
app . use ( '/api/*' , logger ())
app . use ( '/api/*' , cors ())
app . use ( '/api/*' , jwt ({ secret: 'secret' , alg: 'HS256' }))
Middleware Ordering
Middleware order matters! They execute in the order they’re registered:
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { jwt } from 'hono/jwt'
const app = new Hono ()
// ✅ Correct: Logger runs first, then auth
app . use ( '*' , logger ())
app . use ( '/api/*' , jwt ({ secret: 'secret' , alg: 'HS256' }))
// ❌ Wrong: Auth runs before logger
app . use ( '/api/*' , jwt ({ secret: 'secret' , alg: 'HS256' }))
app . use ( '*' , logger ()) // This won't log auth errors
Global middleware (using * or no path) should typically be registered first, followed by more specific path-based middleware.
Middleware Pattern Matching
Path patterns determine when middleware executes:
import { Hono } from 'hono'
import { logger } from 'hono/logger'
const app = new Hono ()
// All routes
app . use ( '*' , logger ())
// Routes starting with /api/
app . use ( '/api/*' , logger ())
// Exact route
app . use ( '/admin' , logger ())
// Routes with parameters
app . use ( '/users/:id' , logger ())
// Multiple segments
app . use ( '/api/v1/*' , logger ())
Built-in vs Custom vs Third-Party
Hono provides three types of middleware:
Built-in Middleware
Shipped with Hono and ready to use:
import { Hono } from 'hono'
import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
import { jwt } from 'hono/jwt'
const app = new Hono ()
app . use ( logger ())
app . use ( '/api/*' , cors ())
app . use ( '/auth/*' , jwt ({ secret: 'secret' , alg: 'HS256' }))
Custom Middleware
Create your own middleware for specific needs:
import { Hono } from 'hono'
import type { MiddlewareHandler } from 'hono'
const app = new Hono ()
const customMiddleware : MiddlewareHandler = async ( c , next ) => {
// Your logic here
await next ()
}
app . use ( customMiddleware )
Third-Party Middleware
Middleware from the community or other compatible libraries:
import { Hono } from 'hono'
import { someThirdPartyMiddleware } from 'third-party-package'
const app = new Hono ()
app . use ( someThirdPartyMiddleware ())
Next Steps
Built-in Middleware Explore all built-in middleware that ships with Hono
Custom Middleware Learn how to create your own middleware
Third-Party Middleware Integrate external middleware packages