Skip to main content

Overview

The RegExpRouter is Hono’s default and most performant router implementation. It uses a sophisticated trie-based algorithm to compile all routes into a single optimized regular expression, eliminating linear loops entirely.

How It Works

The RegExpRouter employs a two-phase approach:
  1. Build Phase: Routes are organized into a trie structure, with static paths separated from dynamic routes
  2. Compilation Phase: The trie is compiled into a highly optimized RegExp with indexed capture groups
  3. Match Phase: Path matching is performed using a single RegExp execution, making it O(1) for static routes

Algorithm Details

  • Uses a Trie data structure to organize routes hierarchically
  • Static routes are stored in a hash map for instant O(1) lookup
  • Dynamic routes are compiled into a single RegExp with numbered capture groups
  • Parameter extraction uses pre-calculated index maps for maximum performance
  • Wildcard middleware patterns are cached and tested separately

Performance Characteristics

Static Routes

O(1) - Direct hash map lookup

Dynamic Routes

O(1) - Single RegExp match

Build Time

O(n log n) - Routes sorted and compiled once

Memory

High - Precompiled matchers cached in memory

When to Use

  • Production applications requiring maximum performance
  • Applications with many routes (100+)
  • Static routes with occasional dynamic parameters
  • Edge computing environments (Cloudflare Workers, Deno Deploy)
  • When route registration happens once at startup

Configuration

The RegExpRouter is used by default in Hono and requires no configuration:
import { Hono } from 'hono'

const app = new Hono() // Uses RegExpRouter by default
To explicitly specify the router:
import { Hono } from 'hono'
import { RegExpRouter } from 'hono/router/reg-exp-router'

const app = new Hono({ router: new RegExpRouter() })

Usage Examples

Basic Routing

import { Hono } from 'hono'

const app = new Hono()

// Static routes (O(1) lookup)
app.get('/', (c) => c.text('Home'))
app.get('/about', (c) => c.text('About'))
app.get('/contact', (c) => c.text('Contact'))

// Dynamic routes
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ userId: id })
})

// Nested parameters
app.get('/posts/:postId/comments/:commentId', (c) => {
  const { postId, commentId } = c.req.param()
  return c.json({ postId, commentId })
})

Route Parameters with Patterns

// Match numeric IDs only
app.get('/users/:id{[0-9]+}', (c) => {
  const id = c.req.param('id')
  return c.json({ userId: id })
})

// Match file extensions
app.get('/files/:filename{.+\\.(jpg|png|gif)}', (c) => {
  const filename = c.req.param('filename')
  return c.json({ file: filename })
})

Optional Parameters

// Optional trailing segment
app.get('/api/v1/users/:id?', (c) => {
  const id = c.req.param('id')
  return c.json({ id: id || 'all' })
})

Wildcard Routes

// Catch-all route
app.get('/static/*', (c) => {
  return c.text('Static file handler')
})

// Wildcard middleware
app.use('/api/*', async (c, next) => {
  console.log('API request:', c.req.path)
  await next()
})

Performance Optimization

import { Hono } from 'hono'

const app = new Hono()

// Group static routes together for optimal hash map performance
app.get('/', (c) => c.text('Home'))
app.get('/about', (c) => c.text('About'))
app.get('/contact', (c) => c.text('Contact'))
app.get('/pricing', (c) => c.text('Pricing'))

// Dynamic routes are compiled into a single RegExp
app.get('/users/:id', (c) => c.json({ id: c.req.param('id') }))
app.get('/posts/:slug', (c) => c.json({ slug: c.req.param('slug') }))
app.get('/categories/:name', (c) => c.json({ name: c.req.param('name') }))

Advanced Features

Method-Specific Matchers

The RegExpRouter builds separate matchers for each HTTP method, optimizing for the most common case where different methods have different route structures:
// Each method gets its own optimized matcher
app.get('/users/:id', getUser)
app.post('/users', createUser)
app.put('/users/:id', updateUser)
app.delete('/users/:id', deleteUser)

Middleware Integration

Wildcard middleware is intelligently applied to routes during the build phase:
// Middleware is attached to routes at build time
app.use('/api/*', authMiddleware)

// These routes will include authMiddleware
app.get('/api/users', listUsers)
app.get('/api/posts', listPosts)

Limitations

The RegExpRouter has some path restrictions:
  • No duplicate parameter names in the same route at different levels
  • No wildcard + parameter combinations like /path/:param/*
  • Ambiguous routes throw errors during compilation
  • Routes cannot be added after the first match (matchers are built lazily)

Unsupported Path Examples

// ❌ Duplicate parameter names
app.get('/:user/posts/:user', handler) // Will throw UnsupportedPathError

// ❌ Wildcard with parameter
app.get('/files/:name/*', handler) // Will throw UnsupportedPathError

// ❌ Ambiguous routes
app.get('/:a/b', handler1)
app.get('/a/:b', handler2) // May throw during match

Internal Architecture

Build Process

// Conceptual build flow
1. Routes collected during app.get(), app.post(), etc.
2. On first match() call:
   a. Routes sorted by static vs dynamic
   b. Static routes stored in hash map
   c. Dynamic routes inserted into trie
   d. Trie compiled to RegExp
   e. Capture group indices mapped to parameters
3. Compiled matchers cached for subsequent requests

Match Process

// Conceptual match flow
1. Check static map: O(1) lookup
2. If not found, execute compiled RegExp: O(1) match
3. Extract capture groups using index map
4. Return handlers with parameters

Comparison with Other Routers

FeatureRegExpRouterTrieRouterLinearRouter
Static routesO(1)O(n)O(n)
Dynamic routesO(1)O(n)O(n)
Memory usageHighMediumLow
Build complexityHighLowNone
All patterns supportedNoYesYes

Source Code Reference

The RegExpRouter implementation can be found at:
  • Router: src/router/reg-exp-router/router.ts
  • Trie: src/router/reg-exp-router/trie.ts
  • Matcher: src/router/reg-exp-router/matcher.ts

See Also

SmartRouter

Automatically selects the best router for your routes

TrieRouter

Tree-based router supporting all path patterns

Routing Guide

Learn about choosing the right router

Performance Guide

Optimize your Hono application

Build docs developers (and LLMs) love