Gabriel Caiana

Persistent Storage in Nuxt with Unstorage


Table of contents
  1. 🧠 What is unstorage?
  2. 📁 Storage structure in Nuxt
  3. 🚀 Example 1: Configuring Unstorage with Redis
  4. 1. Install the driver:
  5. 2. Create the plugin to configure the driver
  6. 3. Using storage in an API route
  7. ☁️ Example 2: Using Cloudflare KV
  8. 1. Create a custom plugin with KV driver:
  9. 2. Storing data:
  10. 📌 Tip: Use .getItem, .setItem and .removeItem
  11. 📚 Official sources (worth saving to favorites):
  12. ✨ Conclusion

If you’ve ever needed to save data server-side using Nuxt — and wanted something simple but flexible — you’ve probably missed a native way to persist information between application restarts.

That’s where unstorage comes in, a minimalist, modular and powerful solution for persistent storage in Nuxt. And the best part: it comes ready to use with Nuxt 3+ and accepts drivers for Redis, Cloudflare KV, SQLite, filesystem, among others.

Today we’re going to see how to configure this from scratch — no mystery — with practical examples using Redis and Cloudflare KV.


🧠 What is unstorage?

It is a lib created by the UnJS team (the same ones behind Nuxt) to serve as a storage abstraction layer. With it, you can save data to disk, in memory, in a remote database (like Redis), and even in services like Cloudflare KV — all using the same API.

And Nuxt already supports this integratedly.


📁 Storage structure in Nuxt

Nuxt allows you to configure storage drivers within the directory:

/server/storage/

Each .json directory or file there represents a namespace (or bucket) in storage.


🚀 Example 1: Configuring Unstorage with Redis

1. Install the driver:

npm install @unstorage/drivers

Redis requires you to have an active instance (local, Docker or cloud).

2. Create the plugin to configure the driver

// plugins/unstorage.redis.ts
import { defineNitroPlugin } from 'nitropack';
import { createStorage } from 'unstorage';
import redisDriver from '@unstorage/drivers/redis';

export default defineNitroPlugin(async (nitroApp) => {
  const storage = createStorage({
    driver: redisDriver({
      url: 'redis://localhost:6379',
    }),
  });

  nitroApp.storage.setMount('/redis', storage);
});

3. Using storage in an API route

// server/api/favorites.post.ts

export default defineEventHandler(async (event) => {
  const body = await readBody(event);
  const { userId, productId } = body;

  await useStorage('redis').setItem(`favorites:${userId}`, productId);

  return { ok: true };
});

You are now saving persistent data to Redis, with one line of code.


☁️ Example 2: Using Cloudflare KV

Cloudflare KV is great for ultra-fast, global key-value storage. Ideal for serverless or distributed apps.

1. Create a custom plugin with KV driver:

// plugins/unstorage.kv.ts
import { defineNitroPlugin } from 'nitropack';
import { createStorage } from 'unstorage';
import cloudflareKVDriver from '@unstorage/drivers/cloudflare-kv';

export default defineNitroPlugin(async (nitroApp) => {
  const storage = createStorage({
    driver: cloudflareKVDriver({
      accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
      namespaceId: process.env.CLOUDFLARE_KV_NAMESPACE!,
      apiToken: process.env.CLOUDFLARE_API_TOKEN!,
    }),
  });

  nitroApp.storage.setMount('/kv', storage);
});

2. Storing data:

// server/api/visits.ts

export default defineEventHandler(async () => {
  const count = (await useStorage('kv').getItem<number>('visits')) || 0;
  await useStorage('kv').setItem('visits', count + 1);
  return { visits: count + 1 };
});

Just like that, your hit counter is now saved globally, with persistence via Cloudflare.


📌 Tip: Use .getItem, .setItem and .removeItem

The unstorage API is super simple and resembles localStorage, but it works server-side:

await useStorage('redis').setItem('key', 'value');
const value = await useStorage('redis').getItem('key');
await useStorage('redis').removeItem('key');

📚 Official sources (worth saving to favorites):


✨ Conclusion

If you want to store persistent data in a Nuxt application, unstorage is the cleanest, most elegant and extensible way. It gives you the freedom to change providers (Redis, SQLite, filesystem, KV…) without changing your logic.

For e-commerce, SaaS, dashboards or microservices — it’s a tool worth having on your belt.