Guide

KV Storage

Nitro provides a built-in storage layer that can abstract filesystem or database or any other data source.

Nitro has built-in integration with unjs/unstorage to provide a runtime agnostic persistent layer.

Usage

To use the storage layer, you can use the useStorage() and call getItem(key) to retrieve an item and setItem(key, value) to set an item.

// Default storage is in memory
await useStorage().setItem('test:foo', { hello: 'world' })
await useStorage().getItem('test:foo')

// You can also specify the base in useStorage(base)
await useStorage('test').setItem('foo', { hello: 'world' })

// You can use data storage to write data to default .data/kv directory
const dataStorage = useStorage('data')
await dataStorage.setItem('test', 'works')
await dataStorage.getItem('data:test') // Value persists

// You can use generics to define types
await useStorage<{ hello: string }>('test').getItem('foo')
await useStorage('test').getItem<{ hello: string }>('foo')
Read more in unstorage.unjs.io.

Configuration

You can mount one or multiple custom storage drivers using the storage config. The key is the mount point name, and the value is the driver name and configuration.

export default defineNitroConfig({
  storage: {
    redis: {
      driver: 'redis',
      /* redis connector options */
    },
    db: {
      driver: 'fs',
      base: './data/db'
    }
  }
})
You can find the driver list on unstorage documentation with their configuration.

Runtime configuration

In scenarios where the mount point configuration is not known until runtime, Nitro can dynamically add mount points during startup using plugins.

import redisDriver from 'unstorage/drivers/redis'

export default defineNitroPlugin(() => {
  const storage = useStorage()

  // Dynamically pass in credentials from runtime configuration, or other sources
  const driver = redisDriver({
      base: 'redis',
      host: useRuntimeConfig().redis.host,
      port: useRuntimeConfig().redis.port,
      /* other redis connector options */
    })

  // Mount driver
  storage.mount('redis', driver)
})
This is a temporary workaround, with a better solution coming in the future! Keep a lookout on the GitHub issue here.

Development-only mount points

By default, Nitro will mount the project directory and some other dirs using the filesystem driver in development time.

// Access to project root dir
const rootStorage = useStorage('root')

// Access to project src dir (same as root by default)
const srcStorage = useStorage('src')

// Access to server cache dir
const cacheStorage = useStorage('cache')

// Access to the temp build dir
const buildStorage = useStorage('build')
You also can use the devStorage key to overwrite the storage configuration during development. This is very useful when you use a database in production and want to use the filesystem in development.

In order to use the devStorage key, you need to use the nitro dev command and the key in the storage option must be the same as the production one.

export default defineNitroConfig({
  // Production
  storage: {
    db: {
      driver: 'redis',
      /* redis connector options */
    }
  },
  // Development
  devStorage: {
    db: {
      driver: 'fs',
      base: './data/db'
    }
  }
})

You will also be able to access to a build namespace in the storage layer only during development. It contains file generated by Nitro.