---
title: "Persistent Storage"
description: "Configure persistent storage for build assets across deployments."
canonical_url: "https://nuxtseo.com/docs/skew-protection/guides/storage-configuration"
last_updated: "2026-07-26T01:07:55.956Z"
---

Nuxt Skew Protection needs persistent storage to preserve previous build assets across deployments.

By default, it uses the filesystem storage located at `node_modules/.cache/nuxt-seo/skew-protection`, but this may not be sufficient
for all deployment environments, especially in CI/CD pipelines where caches may be cleared frequently.

## Retention Periods

You can control how long versions are kept using [`retentionDays`](/docs/skew-protection/api/config#retentiondays-number) and [`maxNumberOfVersions`](/docs/skew-protection/api/config#maxnumberofversions-number). By default, the configuration is set up for optimal crawler compatibility.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  skewProtection: {
    // Keep versions for 45 days
    retentionDays: 45,
    // Keep maximum 15 versions
    maxNumberOfVersions: 15
  }
})
```

Cleanup happens **during build**, removing:

- Versions older than `retentionDays`
- Oldest versions beyond `maxNumberOfVersions`

## GitHub Actions

The default filesystem storage works with GitHub Actions caching to persist build assets between deployments
using the `actions/cache` GitHub Action.

<warning>

The cache key must be unique per deployment, otherwise `actions/cache` won't save new assets (it only saves on cache miss).

</warning>

```yaml [your-github-workflow.yml]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # Install...
      - name: Cache for Nuxt SEO
        uses: actions/cache@v4
        with:
          path: node_modules/.cache/nuxt-seo
          key: nuxt-skew-${{ github.sha }}
          restore-keys: |
            nuxt-skew-
      # Build, etc..
```

The `restore-keys` fallback ensures previous assets are restored, while the unique `github.sha` key ensures new assets are saved after each build.

## Cloudflare

If you have your deployments running through [Cloudflare](https://cloudflare.com) then the `node_modules` folder should automatically persist between deployments, so you do not need any additional configuration.

If you're deploying to Cloudflare using your own CI pipeline, you can use Cloudflare KV storage to persist build assets instead. See the dedicated [Cloudflare Deployment](/docs/skew-protection/providers/cloudflare) guide which covers storage configuration in detail.

## Redis

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  skewProtection: {
    storage: {
      driver: 'redis',
      host: process.env.REDIS_HOST || 'localhost',
      port: Number(process.env.REDIS_PORT) || 6379,
      password: process.env.REDIS_PASSWORD,
      db: 0,
      base: 'skew-protection'
    }
  }
})
```

## Upstash Redis

For serverless deployments like [Netlify](https://netlify.com) or [Vercel](https://vercel.com), [Upstash](https://upstash.com/) provides a Redis-compatible database with an HTTP API.

Install the Upstash [Redis](https://redis.io) client:

```bash [Terminal]
npx nypm add @upstash/redis
```

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  skewProtection: {
    storage: {
      driver: 'upstash',
      url: process.env.UPSTASH_REDIS_REST_URL,
      token: process.env.UPSTASH_REDIS_REST_TOKEN,
      base: 'skew-protection'
    }
  }
})
```

You can find your REST URL and token in the [Upstash Console](https://console.upstash.com/) after creating a database.

## CDN Usage

In cases where you're already using a CDN with long cache times on `/_nuxt/**` assets, you may want to disable persistent storage using [`bundleAssets`](/docs/skew-protection/api/config#bundleassets-boolean).

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  skewProtection: {
    // Disable persistent storage
    bundleAssets: false
  }
})
```
