> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt
> Use this file to discover all available pages before exploring further.

# SmartRouter

> Intelligent router that automatically selects the best routing algorithm for your routes

## Overview

The `SmartRouter` is a meta-router that automatically chooses the optimal routing implementation based on your actual route patterns. It attempts to use the fastest router (RegExpRouter) first, and falls back to more compatible routers (like TrieRouter) if unsupported path patterns are detected.

## How It Works

SmartRouter operates through intelligent router selection:

1. **Initial Setup**: Accepts an array of routers in priority order
2. **Lazy Evaluation**: Routes are collected but not processed until the first match
3. **Auto-Detection**: On first request, tries each router in order
4. **Fallback Logic**: If a router throws `UnsupportedPathError`, tries the next one
5. **Optimization**: Once a router succeeds, it becomes the active router permanently
6. **Delegation**: All future requests go directly to the active router

### Algorithm Details

* Collects routes during application setup (no processing)
* On first `match()` call, iterates through router candidates
* Adds all routes to each candidate router
* First router that successfully matches becomes the active router
* Updates its own `match` method to delegate directly to the active router
* Zero overhead after the first request

## Performance Characteristics

<CardGroup cols={2}>
  <Card title="First Request" icon="clock">
    **O(r × n)** - r routers × n routes (one-time cost)
  </Card>

  <Card title="Subsequent Requests" icon="bolt">
    **O(1)** - Direct delegation to active router
  </Card>

  <Card title="Build Time" icon="hourglass">
    **Lazy** - Deferred until first match
  </Card>

  <Card title="Memory" icon="memory">
    **Low → High** - Depends on selected router
  </Card>
</CardGroup>

## When to Use

<AccordionGroup>
  <Accordion title="✅ Best For">
    * Applications where route patterns may vary
    * When you want optimal performance without manual router selection
    * Projects that might add complex routes later
    * Libraries or frameworks that don't control route patterns
    * Development environments where routes change frequently
    * Applications migrating between different routing strategies
  </Accordion>

  <Accordion title="❌ Not Recommended For">
    * When you need to inspect the router type before first request
    * Applications where the first request must be ultra-fast
    * When you want explicit control over router selection
    * Environments where deterministic behavior is critical
  </Accordion>
</AccordionGroup>

## Configuration

The SmartRouter requires explicit router candidates to be provided:

```typescript theme={null}
import { Hono } from 'hono'
import { SmartRouter } from 'hono/router/smart-router'
import { RegExpRouter } from 'hono/router/reg-exp-router'
import { TrieRouter } from 'hono/router/trie-router'

const app = new Hono({
  router: new SmartRouter({
    routers: [new RegExpRouter(), new TrieRouter()]
  })
})
```

### Router Priority

Routers are tried in the order provided. Always put faster routers first:

```typescript theme={null}
// ✅ Recommended: Fastest first
const router = new SmartRouter({
  routers: [
    new RegExpRouter(),  // Try fastest first
    new TrieRouter(),    // Fallback to most compatible
  ]
})

// ❌ Not optimal: Slower router might be selected unnecessarily
const router = new SmartRouter({
  routers: [
    new TrieRouter(),     // Will always succeed
    new RegExpRouter(),   // Never reached
  ]
})
```

## Usage Examples

### Basic Setup

```typescript theme={null}
import { Hono } from 'hono'
import { SmartRouter } from 'hono/router/smart-router'
import { RegExpRouter } from 'hono/router/reg-exp-router'
import { TrieRouter } from 'hono/router/trie-router'

const app = new Hono({
  router: new SmartRouter({
    routers: [new RegExpRouter(), new TrieRouter()]
  })
})

// Define routes normally
app.get('/', (c) => c.text('Home'))
app.get('/users/:id', (c) => c.json({ id: c.req.param('id') }))
app.get('/posts/:slug', (c) => c.json({ slug: c.req.param('slug') }))

// SmartRouter will select RegExpRouter (all routes are supported)
```

### Automatic Fallback

```typescript theme={null}
import { Hono } from 'hono'
import { SmartRouter } from 'hono/router/smart-router'
import { RegExpRouter } from 'hono/router/reg-exp-router'
import { TrieRouter } from 'hono/router/trie-router'

const app = new Hono({
  router: new SmartRouter({
    routers: [new RegExpRouter(), new TrieRouter()]
  })
})

// Simple routes
app.get('/api/users', getUsers)
app.get('/api/posts', getPosts)

// Complex route that RegExpRouter doesn't support
app.get('/files/:name/*', getFile)  // Wildcard + parameter

// First request: RegExpRouter fails → fallback to TrieRouter
// TrieRouter becomes the active router
```

### Checking Active Router

After the first request, you can check which router was selected:

```typescript theme={null}
const router = new SmartRouter({
  routers: [new RegExpRouter(), new TrieRouter()]
})

const app = new Hono({ router })

// Define routes
app.get('/', (c) => c.text('Home'))
app.get('/users/:id', (c) => c.text('User'))

// Before first request
try {
  console.log(router.activeRouter.name)  // Throws error
} catch (e) {
  console.log('No active router yet')
}

// After first request
await app.fetch(new Request('http://localhost/'))
console.log(router.name)  // "SmartRouter + RegExpRouter"
console.log(router.activeRouter.name)  // "RegExpRouter"
```

### Custom Router Chain

```typescript theme={null}
import { SmartRouter } from 'hono/router/smart-router'
import { RegExpRouter } from 'hono/router/reg-exp-router'
import { TrieRouter } from 'hono/router/trie-router'
import { PatternRouter } from 'hono/router/pattern-router'

// Try multiple routers in priority order
const router = new SmartRouter({
  routers: [
    new RegExpRouter(),   // Fastest, but limited patterns
    new PatternRouter(),  // Moderate speed, more patterns
    new TrieRouter(),     // Slowest, all patterns supported
  ]
})

const app = new Hono({ router })
```

## How Selection Works

### Selection Flow

```typescript theme={null}
// Conceptual selection algorithm
function selectRouter(routers, routes, method, path) {
  for (const router of routers) {
    try {
      // Add all routes to candidate router
      for (const [method, path, handler] of routes) {
        router.add(method, path, handler)
      }
      
      // Try to match the incoming request
      const result = router.match(method, path)
      
      // Success! This router supports all our routes
      return { router, result }
    } catch (error) {
      if (error instanceof UnsupportedPathError) {
        // This router can't handle our routes, try next
        continue
      }
      throw error  // Unexpected error, propagate
    }
  }
  
  throw new Error('No compatible router found')
}
```

### Example Selection Scenarios

<Tabs>
  <Tab title="Scenario 1: Simple Routes">
    ```typescript theme={null}
    // Routes:
    app.get('/', handler)
    app.get('/users/:id', handler)
    app.get('/posts/:slug', handler)

    // Result: RegExpRouter selected
    // Reason: All routes are supported, best performance
    ```
  </Tab>

  <Tab title="Scenario 2: Complex Patterns">
    ```typescript theme={null}
    // Routes:
    app.get('/api/users', handler)
    app.get('/files/:name/*', handler)  // Unsupported by RegExpRouter

    // Result: TrieRouter selected
    // Reason: RegExpRouter fails on wildcard+parameter combination
    ```
  </Tab>

  <Tab title="Scenario 3: All Compatible">
    ```typescript theme={null}
    // Routes:
    app.get('/static/*', handler)
    app.get('/api/:version/users', handler)

    // Result: RegExpRouter selected (if listed first)
    // Reason: All patterns are supported, first router wins
    ```
  </Tab>
</Tabs>

## Advanced Features

### Name Reporting

SmartRouter updates its name to reflect the active router:

```typescript theme={null}
const router = new SmartRouter({
  routers: [new RegExpRouter(), new TrieRouter()]
})

console.log(router.name)  // "SmartRouter"

// After first request
await app.fetch(request)
console.log(router.name)  // "SmartRouter + RegExpRouter"
```

### Zero-Overhead Delegation

After selection, SmartRouter replaces its own `match` method:

```typescript theme={null}
// Before first request
smartRouter.match(method, path)  // Runs selection logic

// After first request
smartRouter.match(method, path)  // Direct delegation to active router
// No performance penalty!
```

### Route Collection

SmartRouter stores routes without processing them:

```typescript theme={null}
const router = new SmartRouter({ routers: [new RegExpRouter()] })
const app = new Hono({ router })

// These calls are very fast - just collecting data
app.get('/route1', handler1)  // Stored
app.get('/route2', handler2)  // Stored
app.get('/route3', handler3)  // Stored
// No trie building, no RegExp compilation yet!

// First request triggers selection and building
await app.fetch(request)  // Now routes are processed
```

## Error Handling

### No Compatible Router

```typescript theme={null}
const router = new SmartRouter({
  routers: [new RegExpRouter()]  // Only one router
})

const app = new Hono({ router })

// Add route that RegExpRouter doesn't support
app.get('/complex/:param/*', handler)

// First request will fail
try {
  await app.fetch(request)
} catch (error) {
  console.error('Fatal error: No compatible router found')
}
```

### Accessing Active Router Too Early

```typescript theme={null}
const router = new SmartRouter({
  routers: [new RegExpRouter(), new TrieRouter()]
})

// Before any requests
try {
  const active = router.activeRouter
} catch (error) {
  // Error: "No active router has been determined yet."
}
```

## Best Practices

<Steps>
  <Step title="Order Routers by Speed">
    Put faster routers first in the array. RegExpRouter should typically be first.

    ```typescript theme={null}
    routers: [new RegExpRouter(), new TrieRouter()]  // ✅ Good
    routers: [new TrieRouter(), new RegExpRouter()]  // ❌ Suboptimal
    ```
  </Step>

  <Step title="Include a Fallback Router">
    Always include a router that supports all patterns (like TrieRouter) as the last option.

    ```typescript theme={null}
    routers: [
      new RegExpRouter(),  // Try fastest
      new TrieRouter(),    // Fallback to most compatible
    ]
    ```
  </Step>

  <Step title="Monitor Active Router">
    In production, log which router was selected to understand your routing patterns.

    ```typescript theme={null}
    app.use('*', async (c, next) => {
      await next()
      if (router.name !== 'SmartRouter') {
        console.log('Active router:', router.activeRouter.name)
      }
    })
    ```
  </Step>
</Steps>

## Comparison with Direct Router Usage

| Aspect              | SmartRouter        | Direct Router    |
| ------------------- | ------------------ | ---------------- |
| First request       | Slower (selection) | Normal speed     |
| Subsequent requests | Same as direct     | Baseline         |
| Route compatibility | Automatic fallback | Manual selection |
| Flexibility         | High               | Low              |
| Predictability      | Lower              | Higher           |
| Complexity          | Lower (auto)       | Higher (manual)  |

## Performance Considerations

<Warning>
  The first request has additional overhead:

  * **Route duplication**: All routes added to each candidate router
  * **Multiple attempts**: Each router tried until one succeeds
  * **Build time**: Selected router builds its internal structures

  For production APIs with strict latency requirements on first request, consider using a router directly.
</Warning>

### Optimization Strategies

```typescript theme={null}
// Strategy 1: Pre-warm the router during startup
const router = new SmartRouter({
  routers: [new RegExpRouter(), new TrieRouter()]
})
const app = new Hono({ router })

// Define all routes
app.get('/', handler)
app.get('/users/:id', handler)

// Trigger router selection before accepting traffic
await app.fetch(new Request('http://localhost/'))
console.log('Router selected:', router.activeRouter.name)
// Now ready for production traffic!

// Strategy 2: Use SmartRouter in development, direct router in production
const router = process.env.NODE_ENV === 'production'
  ? new RegExpRouter()  // Known to work with our routes
  : new SmartRouter({ routers: [new RegExpRouter(), new TrieRouter()] })
```

## Source Code Reference

The SmartRouter implementation can be found at:

* Router: `src/router/smart-router/router.ts`

## See Also

<CardGroup cols={2}>
  <Card title="RegExpRouter" icon="wand-magic-sparkles" href="/api/routers/regexp-router">
    High-performance trie-based RegExp router
  </Card>

  <Card title="TrieRouter" icon="tree" href="/api/routers/trie-router">
    Tree-based router supporting all patterns
  </Card>

  <Card title="Routing Guide" icon="route" href="/routing/routers">
    Learn about choosing the right router
  </Card>

  <Card title="Performance Guide" icon="gauge-high" href="/guides/performance">
    Optimize your Hono application
  </Card>
</CardGroup>
