Skip to content

Migrate: one persistent Valkey β†’ ephemeral auth + persistent data ​

This guide is for projects that already run a single Valkey with rdb+aof (integration snapshots, feeds, etc.) and will adopt a raclette core version that supports auth.valkeyInstances and additional instances via RACLETTE_VALKEY_*_URL.

CACHE_URL and RACLETTE_VALKEY_*_URL are set on the backend container only (app backend vs workbench backend are separate stacks). Frontend containers never use these variables.

What happens if you change nothing? ​

If you keep one Valkey, wire it as CACHE_URL, and leave auth.valkeyInstances unset:

DataInstance id usedWhere it goes
Raclette sessionssessions β†’ "cache"Your persistent Valkey
OAuth CSRF stateoauthState β†’ "cache"Same
OAuth provider tokens (persistProviderTokens)providerTokens β†’ "cache"Same
Login rate limits, fastify.cache, asset tokensfastify.cacheSame
Plugin upstream snapshots (today)fastify.cacheSame

So yes: after upgrading core, OAuth tokens and sessions would also live on that persistent instance unless you reconfigure. That may be acceptable (everything survives restart) but it is usually not what you want once auth can target a separate instance: sessions and tokens are meant to be safe to flush on deploy, while integration snapshots stay on disk.

Target architecture ​

text
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     CACHE_URL          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Valkey "cache"     β”‚ ◄──────────────────────│  Auth: sessions,     β”‚
β”‚  persistence: none  β”‚                        β”‚  OAuth state, tokens β”‚
β”‚  (new, empty)       β”‚                        β”‚  rate limits, short  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                        β”‚  plugin cache        β”‚
                                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     RACLETTE_VALKEY_CACHE_PERSISTENT_URL
β”‚  Valkey             β”‚ ◄──────────────────────  Plugin snapshots only
β”‚  "cachePersistent"  β”‚     (createCacheService on fastify.valkeys…)
β”‚  rdb+aof (existing  β”‚
β”‚  volume & data)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Migration checklist ​

1. Add a new ephemeral Valkey ​

Deploy a second Valkey with no RDB/AOF (or --save ""), empty data dir. This becomes the default cache service in Compose.

Example command:

text
valkey-server --save ""

Expose it on the URL you will use for CACHE_URL (e.g. redis://cache:6379 in Compose, or a new host/port in production).

2. Keep the existing Valkey as the persistent store ​

Do not wipe the volume that already holds your integration data. Point the backend at that server with RACLETTE_VALKEY_CACHE_PERSISTENT_URL (or a custom envVar on the config entry).

  • Backend registers it as fastify.valkeys.cachePersistent when the env var is set.
  • In dev, you can declare kind: valkey with enabled: true and a new empty volume for local testing, or enabled: false and set the env var to your existing host.
  • In production, keep the same container/volume you have today; only the env wiring changes.

3. Update environment variables ​

VariablePoints to
CACHE_URLNew ephemeral Valkey
RACLETTE_VALKEY_CACHE_PERSISTENT_URLExisting aof+rdb Valkey (unchanged data)

Remove any mistaken use of the old URL as the only CACHE_URL once the ephemeral instance exists.

4. raclette.config.js ​

js
export default defineRacletteConfig({
  services: {
    cache: {
      enabled: true,
      port: 6379,
      // new ephemeral service in Compose
    },
    // Document the persistent host for ops; set enabled: false when using an external cluster
    cachePersistent: {
      kind: "valkey",
      enabled: false,
      port: 6380,
      name: "raclette-cache-persistent",
    },
  },
  backend: {
    cache: {
      persistence: "none",
    },
  },
  auth: {
    valkeyInstances: {
      sessions: "cache",
      oauthState: "cache",
      providerTokens: "cache",
    },
  },
})

All three auth roles on "cache" (ephemeral). You do not need to set providerTokens to cachePersistent unless you intentionally want tokens on disk (unusual).

OAuth provider workbench config can omit providerTokenValkeyInstance so resolution stays on auth.valkeyInstances.providerTokens β†’ ephemeral cache.

5. Move plugin snapshot code off fastify.cache ​

Any plugin that today stores upstream API payloads on fastify.cache must use the persistent connection after migration:

ts
import { createCacheService } from "@m/cache/cacheManager"

const persistentStore = createCacheService(
  fastify.fastify.valkeys.cachePersistent,
  { prefix: pluginKey, defaultTtl: -1 },
)

// was: fastify.cache.get("feed")
await persistentStore.get("feed")

Search the project for fastify.cache in integration/sync services and switch only those call sites. Ephemeral plugin caching (if any) can stay on fastify.cache.

See Persistent Valkey for external data option B.

6. Plan a session cutover ​

Sessions and OAuth state move to the empty Valkey. Expect:

  • All users must log in again once CACHE_URL points to the new instance.
  • Old auth:session:* keys on the persistent server are orphaned; you can delete them later with redis-cli if you care about disk (they will not be read).

Schedule this with a maintenance window or accept a one-time re-auth.

7. Provider tokens (persistProviderTokens) ​

If you use persistProviderTokens:

  • New tokens are written to {namespace}:oauth_tokens:{sid} on the ephemeral instance (with the config above).
  • Tokens previously stored on the persistent Valkey (if any) are not migrated automatically; users re-login or you accept re-auth after cutover.

8. Verify after deploy ​

CheckExpected
LoginWorks; keys under auth:session:* only on ephemeral Valkey
Dashboard / feedsStill read snapshot keys from persistent Valkey
Restart ephemeral ValkeyUsers logged out; snapshots still available
Restart persistent ValkeySnapshots return after restart; sessions unaffected if ephemeral stayed up

Docker Compose sketch (dev / on-prem) ​

With declarative config, yarn raclette dev generates the ephemeral cache service and (when cachePersistent.enabled: true) the persistent service. For a manual overlay:

yaml
services:
  cache:
    image: valkey/valkey:9.0-alpine
    command: valkey-server --save ""
    ports: ["6379:6379"]
    networks: [raclette_shared]

  cachePersistent:
    image: valkey/valkey:9.0-alpine
    command: valkey-server --appendonly yes --save 3600 1 300 100 60 10000
    volumes: [existing-customer-cache-data:/data]
    ports: ["6380:6379"]
    networks: [raclette_shared]

  backend:
    environment:
      CACHE_URL: redis://cache:6379
      RACLETTE_VALKEY_CACHE_PERSISTENT_URL: redis://raclette-cache-persistent:6379

Replace existing-customer-cache-data with the volume name you already use. Match container_name / host in the persistent URL to your deployment.

Production notes ​

  • Point CACHE_URL at the new managed/ephemeral endpoint.
  • Point RACLETTE_VALKEY_CACHE_PERSISTENT_URL at the existing cluster that already has aof+rdb and your snapshot keys.
  • Roll out config before or with the core upgrade; run plugin code changes in the same release if snapshots must not disappear during the switch.
  • Do not delete the old persistent volume when adding ephemeral; only change which env var each concern uses.

When you should not split ​

Stay on one persistent Valkey (current setup) if:

  • You are fine with sessions surviving Valkey restart.
  • You do not use persistProviderTokens or external snapshot caching separately.
  • Ops complexity of two instances is not worth it.

In that case: keep a single CACHE_URL, backend.cache.persistence: "rdb+aof", and omit additional RACLETTE_VALKEY_*_URL vars. Auth and data stay together; behaviour matches today.