Overview
Hono provides multiple router implementations, each optimized for different use cases. All routers implement the same Router interface defined in src/router.ts:29:
export interface Router < T > {
name : string
add ( method : string , path : string , handler : T ) : void
match ( method : string , path : string ) : Result < T >
}
SmartRouter (Default)
The default router that automatically selects the best router implementation based on your routes.
import { Hono } from 'hono'
const app = new Hono () // Uses SmartRouter by default
How It Works
From src/router/smart-router/router.ts:21, SmartRouter tries each router until one succeeds:
match ( method : string , path : string ): Result < T > {
const routers = this . #routers
const routes = this . #routes
const len = routers . length
let i = 0
let res
for (; i < len ; i ++) {
const router = routers [ i ]
try {
for ( let i = 0 , len = routes . length ; i < len ; i ++ ) {
router . add ( ... routes [ i ])
}
res = router . match ( method , path )
} catch ( e ) {
if ( e instanceof UnsupportedPathError ) {
continue
}
throw e
}
this . match = router . match . bind ( router )
this . #routers = [ router ]
this . #routes = undefined
break
}
// ...
}
SmartRouter locks onto the first compatible router after the first request, providing optimal performance for subsequent requests.
Benefits
Automatic optimization : Chooses the best router for your route patterns
Zero configuration : Works out of the box
Flexible : Supports all route patterns
RegExpRouter
A high-performance router that uses regular expressions for matching.
import { Hono } from 'hono'
import { RegExpRouter } from 'hono/router/reg-exp-router'
const app = new Hono ({ router: new RegExpRouter () })
Characteristics
Performance : Fast matching using compiled regex patterns
Memory : Pre-builds matcher during initialization
Best for : Complex route patterns with many parameters
Implementation Details
From src/router/reg-exp-router/router.ts:122:
export class RegExpRouter < T > implements Router < T > {
name : string = 'RegExpRouter'
#middleware ?: Record < string , Record < string , HandlerWithMetadata < T >[]>>
#routes ?: Record < string , Record < string , HandlerWithMetadata < T >[]>>
constructor () {
this . #middleware = { [ METHOD_NAME_ALL ]: Object . create ( null ) }
this . #routes = { [ METHOD_NAME_ALL ]: Object . create ( null ) }
}
add ( method : string , path : string , handler : T ) {
// Builds route data structures
// ...
}
}
The router uses a trie structure to build optimized regex patterns:
// From src/router/reg-exp-router/router.ts:34
function buildMatcherFromPreprocessedRoutes < T >(
routes : [ string , HandlerWithMetadata < T >[]][]
) : Matcher < T > {
const trie = new Trie ()
const handlerData : HandlerData < T >[] = []
// Builds regex from trie
const [ regexp , indexReplacementMap , paramReplacementMap ] = trie . buildRegExp ()
// ...
}
TrieRouter
A router using a trie (prefix tree) data structure for efficient route matching.
import { Hono } from 'hono'
import { TrieRouter } from 'hono/router/trie-router'
const app = new Hono ({ router: new TrieRouter () })
Characteristics
Performance : Excellent for static routes and simple patterns
Memory : Efficient memory usage
Best for : Applications with many static routes
Implementation
From src/router/trie-router/router.ts:5:
export class TrieRouter < T > implements Router < T > {
name : string = 'TrieRouter'
#node : Node < T >
constructor () {
this . #node = new Node ()
}
add ( method : string , path : string , handler : T ) {
const results = checkOptionalParameter ( path )
if ( results ) {
for ( let i = 0 , len = results . length ; i < len ; i ++ ) {
this . #node . insert ( method , results [ i ], handler )
}
return
}
this . #node . insert ( method , path , handler )
}
match ( method : string , path : string ) : Result < T > {
return this . #node . search ( method , path )
}
}
LinearRouter
A simple router that linearly iterates through all routes.
import { Hono } from 'hono'
import { LinearRouter } from 'hono/router/linear-router'
const app = new Hono ({ router: new LinearRouter () })
Characteristics
Simplicity : Straightforward implementation
Performance : Slower for many routes, but minimal overhead for few routes
Memory : Minimal memory footprint
Best for : Small applications or microservices with few routes
Implementation
From src/router/linear-router/router.ts:11:
export class LinearRouter < T > implements Router < T > {
name : string = 'LinearRouter'
#routes : [ string , string , T ][] = []
add ( method : string , path : string , handler : T ) {
for (
let i = 0 , paths = checkOptionalParameter ( path ) || [ path ], len = paths . length ;
i < len ;
i ++
) {
this . #routes . push ([ method , paths [ i ], handler ])
}
}
match ( method : string , path : string ) : Result < T > {
const handlers : [ T , Params ][] = []
ROUTES_LOOP : for ( let i = 0 , len = this . #routes . length ; i < len ; i ++ ) {
const [ routeMethod , routePath , handler ] = this . #routes [ i ]
if ( routeMethod === method || routeMethod === METHOD_NAME_ALL ) {
// Pattern matching logic
// ...
}
}
return [ handlers ]
}
}
PatternRouter
A router using regular expressions with named capture groups.
import { Hono } from 'hono'
import { PatternRouter } from 'hono/router/pattern-router'
const app = new Hono ({ router: new PatternRouter () })
Characteristics
Flexibility : Supports complex regex patterns in route definitions
Performance : Good for moderate numbers of routes
Best for : Routes with custom regex patterns
Implementation
From src/router/pattern-router/router.ts:8:
export class PatternRouter < T > implements Router < T > {
name : string = 'PatternRouter'
#routes : Route < T >[] = []
add ( method : string , path : string , handler : T ) {
const endsWithWildcard = path . at ( - 1 ) === '*'
if ( endsWithWildcard ) {
path = path . slice ( 0 , - 2 )
}
// Converts path to regex with named groups
const parts = ( path . match ( / \/ ? ( :w + (?: { (?:(?: { [ \d, ] + } ) | [ ^ } ] ) + } ) ? ) | \/ [ ^ \/\? ] + / g ) || []). map (
( part ) => {
const match = part . match ( / ^ \/ : ( [ ^ { ] + )(?: { ( . * ) } ) ? / )
return match
? `/(?< ${ match [ 1 ] } > ${ match [ 2 ] || '[^/]+' } )`
: part === '/*'
? '/[^/]+'
: part . replace ( / [ . \\ +*[^ \] $() ] / g , ' \\ $&' )
}
)
// ...
}
}
RegExpRouter Best overall performance for most use cases. Recommended for production.
TrieRouter Excellent for static routes. Lower memory usage than RegExpRouter.
SmartRouter Automatically selects the best router. Good default choice.
LinearRouter Simple and lightweight. Best for applications with very few routes.
PatternRouter Flexible regex support. Good for complex patterns.
Choosing a Router
Use SmartRouter (default) when...
You want zero configuration
You’re unsure which router is best
Your route patterns vary in complexity
You want automatic optimization
You have many routes (100+)
You need maximum performance
You use complex route patterns
Memory usage is acceptable
Most routes are static
Memory efficiency is important
You have predictable route patterns
You don’t need complex regex patterns
You have very few routes (less than 10)
Simplicity is a priority
Memory footprint must be minimal
You’re building a microservice
Use PatternRouter when...
You need custom regex patterns
Route complexity varies widely
You want named capture groups
Specifying a Router
Set the router when creating your Hono instance:
import { Hono } from 'hono'
import { RegExpRouter } from 'hono/router/reg-exp-router'
const app = new Hono ({ router: new RegExpRouter () })
From src/hono-base.ts:65, the router option is passed during construction:
export type HonoOptions < E extends Env > = {
strict ?: boolean
router ?: Router <[ H , RouterRoute ]>
getPath ?: GetPath < E >
}
Unsupported Paths
Some routers may throw UnsupportedPathError for certain route patterns:
// From src/router.ts:103
export class UnsupportedPathError extends Error {}
SmartRouter handles this by trying alternative routers:
try {
router . add ( ... routes [ i ])
res = router . match ( method , path )
} catch ( e ) {
if ( e instanceof UnsupportedPathError ) {
continue // Try next router
}
throw e
}