> ## 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.

# LinearRouter

> Straightforward router with minimal overhead and maximum pattern support

## Overview

The `LinearRouter` is the simplest router implementation in Hono. It stores routes in a flat array and matches them sequentially using string operations and minimal RegExp. It has virtually no build overhead and supports all routing patterns.

## How It Works

LinearRouter uses a direct, no-frills approach:

1. **Storage**: Routes stored as simple `[method, path, handler]` tuples
2. **No Preprocessing**: Routes are stored exactly as provided
3. **Sequential Matching**: Each request tests routes one by one
4. **String Operations**: Uses string indexOf and character code checks for speed
5. **Minimal RegExp**: Only uses RegExp for complex parameter patterns

### Algorithm Details

* Routes stored in a flat array, no data structures
* Static routes matched with simple string equality
* Wildcards matched with `indexOf()` operations
* Parameters extracted using string slicing and indexOf
* Parameter patterns compile RegExp on-demand with the `d` flag for indices
* Optional parameters handled by creating multiple route entries
* Combines wildcards and parameters (unlike some other routers)

## Performance Characteristics

<CardGroup cols={2}>
  <Card title="All Routes" icon="gauge">
    **O(n)** - Sequential search, no optimization
  </Card>

  <Card title="Build Time" icon="bolt">
    **O(1)** - Zero preprocessing per route
  </Card>

  <Card title="Memory" icon="memory">
    **Minimal** - Just the route array
  </Card>

  <Card title="Startup Time" icon="rocket">
    **Instant** - No compilation or tree building
  </Card>
</CardGroup>

## When to Use

<AccordionGroup>
  <Accordion title="✅ Best For">
    * Serverless/Lambda functions with cold starts
    * Small applications with \< 20 routes
    * Applications where startup time is critical
    * Development and testing (fast iteration)
    * Learning Hono (simple, predictable behavior)
    * Edge functions with minimal compute time
    * Routes with complex patterns (wildcards + parameters)
  </Accordion>

  <Accordion title="❌ Not Recommended For">
    * Large applications with 100+ routes
    * High-traffic APIs (many requests per second)
    * Applications with mostly static routes (no advantage)
    * When maximum request throughput is required
  </Accordion>
</AccordionGroup>

## Configuration

To use the LinearRouter, specify it when creating your Hono instance:

```typescript theme={null}
import { Hono } from 'hono'
import { LinearRouter } from 'hono/router/linear-router'

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

## Usage Examples

### Basic Routing

```typescript theme={null}
import { Hono } from 'hono'
import { LinearRouter } from 'hono/router/linear-router'

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

// Static routes
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 })
})

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

### Advanced Patterns

LinearRouter supports all routing patterns:

```typescript theme={null}
// Wildcards
app.get('/static/*', (c) => c.text('Static files'))

// Wildcards in middle of path
app.get('/api/*/status', (c) => c.text('Status'))

// Parameters with patterns
app.get('/users/:id{[0-9]+}', (c) => {
  const id = c.req.param('id')  // Guaranteed numeric
  return c.json({ userId: parseInt(id) })
})

// Complex patterns
app.get('/files/:name{.+\\.(jpg|png|gif)}', (c) => {
  const name = c.req.param('name')
  return c.json({ filename: name })
})
```

### Wildcard + Parameter Combinations

Unlike RegExpRouter, LinearRouter supports combining wildcards with parameters:

```typescript theme={null}
// ✅ Supported by LinearRouter
app.get('/users/:id/*', (c) => {
  const id = c.req.param('id')
  return c.json({ userId: id, sub: c.req.path })
})

// Complex combinations
app.get('/orgs/:org/*/members/:id', (c) => {
  const { org, id } = c.req.param()
  return c.json({ org, memberId: id })
})
```

<Warning>
  Routes combining wildcards (`*`) with parameters (`:name`) will throw `UnsupportedPathError`. This is a known limitation.
</Warning>

### Optional Parameters

```typescript theme={null}
// Optional parameter
app.get('/docs/:page?', (c) => {
  const page = c.req.param('page') || 'index'
  return c.json({ page })
})

// Creates two routes internally:
// 1. /docs/:page
// 2. /docs
```

### Catch-All Routes

```typescript theme={null}
// Match everything
app.get('*', (c) => c.text('Catch all'))
app.get('/*', (c) => c.text('Catch all with slash'))

// Both are treated specially for performance
```

## How Matching Works

### Matching Algorithm

LinearRouter optimizes for common cases:

```typescript theme={null}
// Conceptual matching algorithm
function match(method: string, path: string) {
  const handlers = []
  
  for (const [routeMethod, routePath, handler] of this.#routes) {
    if (routeMethod !== method && routeMethod !== 'ALL') {
      continue  // Skip wrong method
    }
    
    // Fast path: exact match or with trailing slash
    if (routePath === path || routePath + '/' === path) {
      handlers.push([handler, {}])
      continue
    }
    
    // Special fast path: catch-all
    if (routePath === '*' || routePath === '/*') {
      handlers.push([handler, {}])
      continue
    }
    
    // Has wildcard but no parameters
    if (hasStar && !hasLabel) {
      // Use string indexOf for fast wildcard matching
      const parts = routePath.split('*')
      if (matchesWildcardPattern(path, parts)) {
        handlers.push([handler, {}])
      }
      continue
    }
    
    // Has parameters but no wildcard
    if (hasLabel && !hasStar) {
      // Extract parameters using string operations
      const params = extractParams(path, routePath)
      if (params) {
        handlers.push([handler, params])
      }
      continue
    }
    
    // Has both parameters and wildcards
    if (hasLabel && hasStar) {
      throw new UnsupportedPathError()  // Not supported
    }
  }
  
  return [handlers]
}
```

### Optimization Strategies

```typescript theme={null}
// LinearRouter uses character code checks for speed
if (path.charCodeAt(pos) === 47) {  // Check for '/' character
  // Process path separator
}

if (routePath.charCodeAt(routePath.length - 1) === 42) {  // Check for '*'
  // Handle trailing wildcard
}
```

## Performance Characteristics by Route Type

<Tabs>
  <Tab title="Static Routes">
    ```typescript theme={null}
    // Best case: Early in route list + exact match
    app.get('/', handler)      // 1 iteration
    app.get('/api', handler)   // 2 iterations (if '/' checked first)

    // Worst case: Last route
    app.get('/zzz', handler)   // n iterations

    // Optimization: Put frequent routes first!
    ```
  </Tab>

  <Tab title="Wildcard Routes">
    ```typescript theme={null}
    // Wildcards use indexOf operations
    app.get('/static/*', handler)       // O(m) string search
    app.get('/api/*/status', handler)   // O(m) per part

    // Catch-all is optimized
    app.get('*', handler)   // O(1) check
    ```
  </Tab>

  <Tab title="Parameter Routes">
    ```typescript theme={null}
    // Parameters extract via string slicing
    app.get('/users/:id', handler)  // O(m) to find '/' positions

    // With pattern: compiles RegExp on first match
    app.get('/users/:id{[0-9]+}', handler)  // O(m) + RegExp
    ```
  </Tab>
</Tabs>

## Advanced Features

### Parameter Pattern Matching

LinearRouter uses the RegExp `d` flag for efficient parameter extraction:

```typescript theme={null}
// Pattern: /users/:id{[0-9]+}
app.get('/users/:id{[0-9]+}', handler)

// Internally creates:
const pattern = '[0-9]+'
const regex = new RegExp(pattern, 'd')  // 'd' flag for indices
const match = regex.exec(restOfPath)

// Uses match.indices to extract exact parameter boundaries
value = path.slice(...match.indices[0])
```

### Trailing Slash Handling

Automatically handles trailing slashes:

```typescript theme={null}
app.get('/users/:id', handler)

// Both match:
// GET /users/123   ✓
// GET /users/123/  ✓
```

### Method Matching

Method check happens before route matching for efficiency:

```typescript theme={null}
app.get('/api', getHandler)
app.post('/api', postHandler)

// POST /api
// 1. Check GET route: method mismatch → skip
// 2. Check POST route: method match → test path → match!
```

## Optimization Tips

<Tip>
  Maximize LinearRouter performance:

  1. **Order by frequency** - Put most-hit routes first
  2. **Minimize route count** - Fewer routes = faster matching
  3. **Use static paths** - Faster than parameters or wildcards
  4. **Avoid complex patterns** - Simple parameters are faster
  5. **Group by method** - Method check is cheap
</Tip>

### Optimization Example

```typescript theme={null}
// ✅ Optimized: Hot path first
app.get('/', homeHandler)                    // Most traffic
app.get('/api/health', healthHandler)        // Health checks frequent
app.get('/api/users/:id', getUserHandler)    // Common API call
app.get('/admin/*', adminHandler)            // Rare

// ❌ Not optimized: Rare routes first
app.get('/admin/debug/logs/*', logsHandler)  // Rarely accessed
app.get('/', homeHandler)                     // Should be first!
```

## Use Cases

### Perfect for Serverless

```typescript theme={null}
// AWS Lambda / Cloudflare Workers
import { Hono } from 'hono'
import { LinearRouter } from 'hono/router/linear-router'

// Zero cold-start overhead from routing
const app = new Hono({ router: new LinearRouter() })

app.get('/', (c) => c.text('Hello'))
app.get('/api/:resource', (c) => c.json({ resource: c.req.param('resource') }))

export default app
// Starts instantly, no trie building or RegExp compilation!
```

### Microservices with Few Routes

```typescript theme={null}
// Service with 5-10 routes
const app = new Hono({ router: new LinearRouter() })

// Each microservice has limited routes
app.get('/health', health)
app.get('/ready', ready)
app.get('/metrics', metrics)
app.get('/api/resource/:id', getResource)
app.post('/api/resource', createResource)

// Linear search is fine with so few routes!
```

## Limitations

<Warning>
  LinearRouter limitations:

  * **O(n) for all routes** - No fast path for static routes
  * **No route deduplication** - Duplicate routes both match
  * **Order dependent** - Route order matters significantly
  * **No wildcard + parameter** - Throws UnsupportedPathError
</Warning>

### Unsupported Patterns

```typescript theme={null}
// ❌ Wildcard + parameter combination
app.get('/users/:id/*', handler)  // Throws UnsupportedPathError
app.get('/:org/repos/*/issues/:id', handler)  // Throws UnsupportedPathError
```

## Comparison with Other Routers

| Feature         | LinearRouter | PatternRouter | TrieRouter | RegExpRouter |
| --------------- | ------------ | ------------- | ---------- | ------------ |
| Static routes   | O(n)         | O(n)          | O(n)       | O(1)         |
| Dynamic routes  | O(n)         | O(n)          | O(n×m)     | O(1)         |
| Pattern support | Good         | Good          | Excellent  | Limited      |
| Startup time    | Instant      | Fast          | Fast       | Slow         |
| Memory          | Minimal      | Low           | Medium     | High         |
| Complexity      | Minimal      | Low           | Medium     | High         |
| Route limit     | \< 20        | \< 50         | \< 200     | Unlimited    |

## When Linear is Better

<CardGroup cols={2}>
  <Card title="Cold Start Optimization" icon="snowflake">
    LinearRouter has zero build overhead, making it perfect for serverless functions where cold start time matters more than request speed.
  </Card>

  <Card title="Simple Applications" icon="hand-sparkles">
    For apps with \< 20 routes, the performance difference is negligible and the simplicity is valuable.
  </Card>

  <Card title="Complex Patterns" icon="puzzle-piece">
    When you need wildcard + parameter combinations, LinearRouter is more capable than RegExpRouter.
  </Card>

  <Card title="Development Speed" icon="gauge-high">
    Zero compilation time means instant feedback during development.
  </Card>
</CardGroup>

## Internal Architecture

### Route Storage

```typescript theme={null}
class LinearRouter<T> {
  name = 'LinearRouter'
  #routes: [string, string, T][] = []  // [method, path, handler]
}
```

### Add Method

```typescript theme={null}
add(method: string, path: string, handler: T) {
  // Handle optional parameters
  const paths = checkOptionalParameter(path) || [path]
  
  // Add each variant
  for (const p of paths) {
    this.#routes.push([method, p, handler])
  }
}
```

### Match Method

See "How Matching Works" section above for the detailed algorithm.

## Source Code Reference

The LinearRouter implementation can be found at:

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

## See Also

<CardGroup cols={2}>
  <Card title="PatternRouter" icon="diagram-project" href="/api/routers/pattern-router">
    Simple router using RegExp patterns
  </Card>

  <Card title="SmartRouter" icon="brain" href="/api/routers/smart-router">
    Automatically select the best router
  </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>
