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

# Adapter

> Runtime detection and environment variable access

The Adapter helper provides utilities for detecting the current JavaScript runtime and accessing environment variables in a runtime-agnostic way. This enables writing code that works across different platforms like Node.js, Deno, Bun, Cloudflare Workers, and more.

## Import

```typescript theme={null}
import { env, getRuntimeKey } from 'hono/adapter'
```

## Runtime Detection

### getRuntimeKey

Detect the current JavaScript runtime:

```typescript theme={null}
import { getRuntimeKey } from 'hono/adapter'

const runtime = getRuntimeKey()
console.log(runtime) // 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'other'
```

**Returns**: `Runtime` - A string identifying the current runtime

```typescript theme={null}
type Runtime = 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'other'
```

### Supported Runtimes

* `'node'` - Node.js
* `'deno'` - Deno
* `'bun'` - Bun
* `'workerd'` - Cloudflare Workers
* `'fastly'` - Fastly Compute
* `'edge-light'` - Vercel Edge Runtime and similar
* `'other'` - Unknown or unsupported runtime

## Environment Variables

### env

Access environment variables in a runtime-agnostic way:

```typescript theme={null}
import { env } from 'hono/adapter'

app.get('/var', (c) => {
  const { DATABASE_URL } = env<{ DATABASE_URL: string }>(c)
  return c.json({ url: DATABASE_URL })
})
```

**Parameters**:

<ParamField path="c" type="Context" required>
  The Hono context object
</ParamField>

<ParamField path="runtime" type="Runtime">
  Optional runtime override. If not specified, automatically detected using `getRuntimeKey()`
</ParamField>

**Returns**: `T & Context['env']` - Object containing environment variables

## Type-safe Environment Variables

### With Generic Type Parameter

Define environment variable types inline:

```typescript theme={null}
import { env } from 'hono/adapter'

app.get('/config', (c) => {
  const { API_KEY, PORT, DEBUG } = env<{
    API_KEY: string
    PORT: string
    DEBUG: string
  }>(c)
  
  return c.json({
    apiKey: API_KEY,
    port: parseInt(PORT),
    debug: DEBUG === 'true',
  })
})
```

### With Hono Generics

Define environment variables at the application level:

```typescript theme={null}
import { Hono } from 'hono'
import { env } from 'hono/adapter'

type Env = {
  Bindings: {
    DATABASE_URL: string
    API_KEY: string
    ENVIRONMENT: 'development' | 'production'
  }
}

const app = new Hono<Env>()

app.get('/env', (c) => {
  const { DATABASE_URL, API_KEY, ENVIRONMENT } = env(c)
  
  // All variables are properly typed
  return c.json({
    db: DATABASE_URL,
    key: API_KEY,
    env: ENVIRONMENT,
  })
})
```

### Combined Approach

Combine both generic types:

```typescript theme={null}
import { env } from 'hono/adapter'

type Env = {
  Bindings: {
    DATABASE_URL: string
  }
}

const app = new Hono<Env>()

app.get('/config', (c) => {
  const { DATABASE_URL, EXTRA_VAR } = env<{
    DATABASE_URL: string
    EXTRA_VAR: string
  }>(c)
  
  return c.json({ DATABASE_URL, EXTRA_VAR })
})
```

## Runtime-specific Behavior

The `env` function adapts to different runtimes automatically:

### Node.js and Bun

Accesses `process.env`:

```typescript theme={null}
const { DATABASE_URL } = env(c)
// Reads from process.env.DATABASE_URL
```

### Deno

Accesses `Deno.env.toObject()`:

```typescript theme={null}
const { DATABASE_URL } = env(c)
// Reads from Deno.env.get('DATABASE_URL')
```

### Cloudflare Workers

Accesses environment bindings from context:

```typescript theme={null}
const { DATABASE_URL } = env(c)
// Reads from c.env.DATABASE_URL (Cloudflare bindings)
```

### Fastly Compute

Returns empty object (use ConfigStore instead):

```typescript theme={null}
const vars = env(c)
// Returns {} - use Fastly ConfigStore API for configuration
```

### Edge Runtime

Accesses `process.env`:

```typescript theme={null}
const { DATABASE_URL } = env(c)
// Reads from process.env.DATABASE_URL
```

## Use Cases

### Runtime-specific Configuration

Adjust behavior based on runtime:

```typescript theme={null}
import { getRuntimeKey } from 'hono/adapter'

app.get('/info', (c) => {
  const runtime = getRuntimeKey()
  
  const config = {
    node: { features: ['filesystem', 'native-modules'] },
    deno: { features: ['typescript', 'web-standard'] },
    bun: { features: ['fast-startup', 'native-bundler'] },
    workerd: { features: ['edge-computing', 'global-network'] },
  }[runtime] || { features: [] }
  
  return c.json({ runtime, ...config })
})
```

### Database Connection

Connect to database using environment variables:

```typescript theme={null}
import { env } from 'hono/adapter'

type Env = {
  Bindings: {
    DATABASE_URL: string
    DATABASE_POOL_SIZE: string
  }
}

const app = new Hono<Env>()

app.get('/db', async (c) => {
  const { DATABASE_URL, DATABASE_POOL_SIZE } = env(c)
  
  const db = await connectToDatabase({
    url: DATABASE_URL,
    poolSize: parseInt(DATABASE_POOL_SIZE || '10'),
  })
  
  const users = await db.query('SELECT * FROM users')
  return c.json(users)
})
```

### API Keys and Secrets

Access API keys securely:

```typescript theme={null}
import { env } from 'hono/adapter'

app.get('/external-api', async (c) => {
  const { API_KEY } = env<{ API_KEY: string }>(c)
  
  const response = await fetch('https://api.example.com/data', {
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
    },
  })
  
  return c.json(await response.json())
})
```

### Feature Flags

Implement feature flags with environment variables:

```typescript theme={null}
import { env } from 'hono/adapter'

app.get('/feature', (c) => {
  const { FEATURE_NEW_UI, FEATURE_BETA } = env<{
    FEATURE_NEW_UI?: string
    FEATURE_BETA?: string
  }>(c)
  
  const features = {
    newUI: FEATURE_NEW_UI === 'true',
    beta: FEATURE_BETA === 'true',
  }
  
  return c.json({ features })
})
```

## Manual Runtime Override

Override automatic runtime detection when needed:

```typescript theme={null}
import { env } from 'hono/adapter'

app.get('/force-node', (c) => {
  // Force Node.js environment variable access
  const vars = env(c, 'node')
  return c.json(vars)
})
```

## Known User Agents

The helper uses user agents for runtime detection:

```typescript theme={null}
const knownUserAgents = {
  deno: 'Deno',
  bun: 'Bun',
  workerd: 'Cloudflare-Workers',
  node: 'Node.js',
}
```

## Detection Priority

Runtime detection follows this priority:

1. Check `navigator.userAgent` against known user agents
2. Check for `EdgeRuntime` global (Edge Runtime)
3. Check for `fastly` global (Fastly Compute)
4. Check `process.release.name === 'node'` (Node.js)
5. Return `'other'` if none match

## Type Definitions

```typescript theme={null}
type Runtime = 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'other'

function getRuntimeKey(): Runtime

function env<
  T extends Record<string, unknown>,
  C extends Context = Context<{ Bindings: T }>
>(
  c: T extends Record<string, unknown> ? Context : C,
  runtime?: Runtime
): T & C['env']
```

## Best Practices

<CardGroup cols={2}>
  <Card title="Type Your Environment" icon="check">
    Always provide TypeScript types for environment variables to catch errors early
  </Card>

  <Card title="Use Hono Bindings" icon="link">
    Define environment types in Hono's generic `Bindings` for better type inference
  </Card>

  <Card title="Validate Variables" icon="shield">
    Validate that required environment variables exist before using them
  </Card>

  <Card title="Avoid Runtime Checks" icon="gauge-high">
    Rely on automatic detection rather than manual runtime checking when possible
  </Card>
</CardGroup>

<Note>
  For Cloudflare Workers, environment variables are accessed via bindings (`c.env`) rather than traditional environment variables. The `env` helper handles this automatically.
</Note>

<Warning>
  On Fastly Compute, standard environment variables are not available. Use the Fastly ConfigStore API for configuration data instead.
</Warning>

## Error Handling

Handle missing environment variables gracefully:

```typescript theme={null}
import { env } from 'hono/adapter'

app.get('/secure', (c) => {
  const { SECRET_KEY } = env<{ SECRET_KEY?: string }>(c)
  
  if (!SECRET_KEY) {
    return c.json({ error: 'SECRET_KEY not configured' }, 500)
  }
  
  return c.json({ message: 'Secret key is configured' })
})
```
