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:
| Data | Instance id used | Where it goes |
|---|---|---|
| Raclette sessions | sessions β "cache" | Your persistent Valkey |
| OAuth CSRF state | oauthState β "cache" | Same |
OAuth provider tokens (persistProviderTokens) | providerTokens β "cache" | Same |
Login rate limits, fastify.cache, asset tokens | fastify.cache | Same |
| Plugin upstream snapshots (today) | fastify.cache | Same |
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 β
βββββββββββββββββββββββ 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:
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.cachePersistentwhen the env var is set. - In dev, you can declare
kind: valkeywithenabled: trueand a new empty volume for local testing, orenabled: falseand 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 β
| Variable | Points to |
|---|---|
CACHE_URL | New ephemeral Valkey |
RACLETTE_VALKEY_CACHE_PERSISTENT_URL | Existing 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 β
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:
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_URLpoints to the new instance. - Old
auth:session:*keys on the persistent server are orphaned; you can delete them later withredis-cliif 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 β
| Check | Expected |
|---|---|
| Login | Works; keys under auth:session:* only on ephemeral Valkey |
| Dashboard / feeds | Still read snapshot keys from persistent Valkey |
| Restart ephemeral Valkey | Users logged out; snapshots still available |
| Restart persistent Valkey | Snapshots 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:
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:6379Replace 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_URLat the new managed/ephemeral endpoint. - Point
RACLETTE_VALKEY_CACHE_PERSISTENT_URLat 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
persistProviderTokensor 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.