KV usage
After the quickstart works, most KV code falls into four patterns: choose stable keys, store JSON values, group related keys with prefixes, and keep provider details out of route code.
Import the Runtime Handle
Use the canonical portable import from server/runtime code:
import { kv } from '@vitehub/kv'
The handle is backed by Nitro storage. Nitro mounts the active driver at startup, and Nuxt uses that Nitro path under the hood.
Set and Get JSON Values
kv.set() stores one value. kv.get() returns that value or null when the key is missing.
await kv.set('settings', {
theme: 'system',
notifications: true,
})
const settings = await kv.get<{
theme: string
notifications: boolean
}>('settings')
Route example:
import { kv } from '@vitehub/kv'
export default defineEventHandler(async () => {
const settings = await kv.get('settings')
return {
settings: settings ?? {
theme: 'system',
notifications: true,
},
}
})
Use Prefixes for Related Keys
KV keys are strings. Use prefixes when a feature owns a group of values:
await kv.set('users:ava:preferences', { density: 'compact' })
await kv.set('users:ava:flags', { beta: true })
Then list only that group:
const userKeys = await kv.keys('users:ava')
Example response:
{
"keys": [
"users:ava:flags",
"users:ava:preferences"
]
}
Check Before Doing Expensive Work
Use kv.has() when the value is not needed:
if (await kv.has('reports:daily:2026-04-26')) {
return { cached: true }
}
Use kv.get() when the route needs the value anyway. That avoids a separate round trip for remote providers.
Delete One Key
await kv.del('settings')
Use this for explicit user actions such as resetting preferences or removing a cache entry.
Clear a Prefix
kv.clear() clears the whole active store. Pass a prefix when only one feature namespace should be removed:
await kv.clear('users:ava')
kv.clear() carefully. In hosted providers it targets the configured namespace or database, not only the current route.Keep Provider Logic in Config
Route code should look the same for local, Cloudflare, and Vercel:
await kv.set('settings', { enabled: true })
return { settings: await kv.get('settings') }
Provider details belong in config:
kv: {
driver: 'fs-lite',
base: '.data/kv',
}
kv: {
driver: 'cloudflare-kv-binding',
binding: 'KV',
namespaceId: '<kv-namespace-id>',
}
kv: {
driver: 'upstash',
}
Pass Driver-Specific Options Intentionally
Every method accepts an optional options argument and passes it to the underlying unstorage driver:
await kv.set('settings', { enabled: true }, {
ttl: 60,
})
Those options are driver-specific. ViteHub does not currently define a portable option contract for TTLs, metadata, or consistency behavior.
Disable KV
Set kv: false when a Nuxt or Nitro app should install the package but not mount runtime KV:
export default defineNuxtConfig({
modules: ['@vitehub/kv/nuxt'],
kv: false,
})
Next Steps
- Use Write and read values for complete route examples.
- Use Choose a driver when deciding between local, Cloudflare, and Vercel.
- Use Runtime API for method signatures and config types.

