Laravel Redis to Valkey: A Safe Migration Guide

Migrate Laravel from Redis to Valkey with version checks, cache and session planning, queue draining, a tested local fixture and a clear recovery boundary.

Adrian Silaghi

9 min read

0 views

LaravelRedisValkeyQueuesSessionsMigration
Laravel Redis to Valkey: A Safe Migration Guide

Move a Laravel application from Redis to Valkey by inventorying every connection and data purpose, checking the source version, and rehearsing a controlled cutover. A host change may be enough for a disposable cache. Sessions, queues, locks and persistent data need an explicit transfer and recovery plan. Do not promise that users will remain signed in or jobs cannot be duplicated merely because both servers speak the Redis protocol.

The first version gate is essential: Valkey's official migration guide supports the compatible Redis OSS 7.2-and-earlier path, but says data files from Redis Community Edition 7.4 and later are incompatible. A generic “copy dump.rdb” tutorial is therefore unsafe for an uninspected source.

Inventory the data, not just REDIS_HOST

Laravel may use several logical connections, databases and prefixes on the same Redis server. Make a small table of each consumer and who can stop its writes:

PurposeWhat migration must preserve or deliberately reset
CacheRebuild behavior, warm-up load and acceptable misses.
SessionsSession bytes, remaining TTL, key prefix and application cookie/encryption settings.
QueuesReady, reserved and delayed jobs, plus producers and workers.
Locks and rate limitsOwnership/expiry behavior and the ability to prevent split lock domains.
Persistent application dataTypes, values, expiration semantics, modules and recovery requirements.
HorizonIts connection, prefix, supervisors and operational metadata.

Inspect your own config/database.php, cache.php, session.php, queue.php and Horizon configuration where installed. Also search deployment secrets for URL-based connections: an unchanged REDIS_URL can override the host you thought you replaced. Do not print password-bearing URLs into a ticket or build log.

Laravel's Redis configuration guide covers PhpRedis, Predis, connection databases, prefixes and client options. Keep these settings in your migration record. Protocol compatibility does not guarantee that a different serializer or compression configuration will decode the application's existing values.

Check the exact source and target versions

Use an authenticated administrative connection to inspect the server. These diagnostic commands are useful on each endpoint:

INFO SERVER
INFO KEYSPACE
INFO PERSISTENCE
INFO REPLICATION
MODULE LIST

Some managed services restrict commands, so use their supported inspection method when necessary. On Valkey, inspect server_name and valkey_version; do not identify it solely from redis_version, which can exist for compatibility. The INFO reference explains server and operational sections.

SourcePlanning rule
Redis OSS 7.2 or earlierEvaluate the documented compatible snapshot or replication path and verify your commands/modules.
Redis CE 7.4 or laterDo not use this physical-copy recipe. Select a separately validated migration method or rebuild only genuinely disposable data.
Redis-compatible managed service or modulesObtain the provider's compatibility and migration procedure; product naming alone is insufficient.

Replication is not a workaround for an incompatible snapshot format: a full synchronization transfers a snapshot too. Changing the command from file copy to REPLICAOF does not remove that gate. Nor should a DUMP/RESTORE loop be assumed to bypass serialized-format incompatibilities. Custom key-level transfers need type, TTL and command compatibility tests of their own.

Preserve client settings before changing endpoints

For Laravel 12, keep the existing Redis driver and client unless you have a separate reason to change them. A Valkey move does not inherently require replacing PhpRedis with another PHP library. Preserve logical database numbers, prefixes, serialization and compression settings, and verify TLS and ACL credentials on the destination.

Prefer a connection-by-connection rollout when the state is genuinely independent. A dedicated disposable cache can move before a queue or session store. However, two endpoints used for the same distributed lock create two authorities; independent workers may both acquire what they believe is the same lock. Keep all participants in one lock domain throughout the transition.

The Laravel cache guide describes atomic locks and shared cache requirements. Avoid cache:clear, FLUSHDB or FLUSHALL as migration preparation on a shared store. Besides ordinary cache entries, the same server may hold locks, restart signals or unrelated application data.

For sessions, keep the application key, cookie name/domain, session connection, prefix and lifetime consistent unless you intentionally want a reset. Laravel's session guide documents the Redis connection setting. Rehearse with the real serializer and representative opaque session values, while protecting their contents as account data.

Choose a transfer method that fits the data

Disposable cache: rebuild deliberately

If a connection contains only recreatable cache entries, starting empty can be simpler than transferring it. Estimate the effect of cold reads on PostgreSQL, upstream APIs and application latency. Warm expensive entries gradually, monitor origin load and ensure locks or sessions are not mixed into the supposedly disposable namespace.

Compatible snapshot: allow a write pause

For a compatible source, a physical migration takes a current consistent snapshot, restores it into a separately configured Valkey installation and then reconnects clients. Stop all writers before the final snapshot so later updates are not silently left behind. Check the backup completed successfully, use the correct data directory and verify the restored keyspaces before reopening traffic.

Plan sufficient memory and disk for the target, snapshot creation and loading. Decide whether RDB, AOF or both are required for ongoing durability; transferring one snapshot does not configure future backups. The Valkey persistence guide distinguishes periodic snapshots from append-only logging and their recovery tradeoffs.

Compatible replication: monitor synchronization, then fence writers

A separate target can follow the compatible source while you prepare. Verify the initial copy completes and the replication link stays healthy. Before promotion, stop source writes, let replication catch up, verify offsets and representative data, then prevent clients from reconnecting to the old writer.

Valkey replication is asynchronous. A healthy link alone is not proof that the last application write reached the replica. Full resynchronization uses a snapshot, and acknowledgment mechanisms do not turn the system into a universally lossless failover service. See the replication documentation.

This guide's operational sequence is for standalone instances. Redis Cluster, Sentinel and managed failover systems require their own topology-specific migration procedure; do not apply standalone promotion commands to them blindly.

Drain work without discarding future jobs

For Laravel queues, stop producers before expecting a stable backlog. Producers include HTTP requests, scheduled commands, webhook ingestion and other services, not only the worker process. Then let in-flight jobs finish and confirm acknowledgments. A ready-list count of zero does not prove the queue is empty: reserved and delayed jobs can still exist.

Choose explicitly whether to finish the ready backlog before the pause or transfer it consistently. Future delayed jobs may need to move even when every currently running job has completed. Inventory unique-job locks and failed-job storage separately; those can use different connections or a database. Keep normal retry and idempotency rules in place.

The Laravel queue documentation explains long-lived workers, graceful restarts and Redis queue configuration. Coordinate your process manager so workers cannot immediately restart against the old endpoint while you are moving state. A queue:restart signal by itself is not a global writer fence, and its cache-backed signal needs to reach the workers you intend to stop.

With Horizon, account for its own supervisor lifecycle. horizon:terminate allows current jobs to finish, but a process manager may start Horizon again. Suspend automatic restarts for the planned pause, change the reviewed configuration, and resume deliberately. The Horizon deployment guide describes termination and supervision.

Use a single coordinated cutover

  1. Rehearse: validate your actual PHP client, configuration and relevant data types against a separate target.
  2. Prepare recovery: retain a consistent source backup and record the old endpoint/configuration.
  3. Fence writers: pause producers, drain in-flight work and hold worker restarts. Protect lock-based operations from split ownership.
  4. Complete transfer: take the final snapshot or confirm replication caught up after the write pause.
  5. Change configuration: update every affected connection or URL, rebuild Laravel's configuration cache through your deployment process and restart long-lived application processes.
  6. Validate before reopening: check sessions, queue processing, TTLs and locks using controlled test actions.
  7. Resume gradually: watch errors, queue age, cache misses, evictions and origin load while keeping the old source fenced.

Compare keyspaces and representative values, not only PING. Preserve remaining expiry rather than turning session keys into permanent records or restarting their lifetime. PTTL reports remaining milliseconds and distinguishes missing keys from keys without expiry. If using SCAN, complete the cursor cycle, account for duplicates and remember that scanning a changing dataset is not a consistent snapshot.

Download the isolated native rehearsal. It starts its own Redis 7.2.5 and Valkey 8.1.3 fixture processes, verifies strings, hashes, lists, sorted sets and TTLs after replication, promotes the target and checks a new target-only write. These fixture versions document the compatibility check, not a production patch recommendation. It does not validate Laravel sessions, real job execution, TLS, modules or production scale.

Do not confuse the old server with a current rollback copy

Before the destination accepts writes, abandoning it and reconnecting to an unchanged source is relatively straightforward. After new writes, the source is stale: sessions may have changed, jobs may have been consumed, and locks may have expired or been reacquired. Switching back can repeat work or discard state.

Define the point where recovery requires reconciliation rather than a host reversal. Reconcile queue jobs using business identifiers and downstream records, especially where a job sends mail or charges a payment method. Retain backups and the old configuration for an agreed period, then remove them only after the new store and its own recovery process have been accepted.

For the surrounding deployment, our Docker Compose VPS guide and managed apps versus self-hosting comparison help frame operating responsibilities. Explore DanubeData VPS hosting if you need a separate environment for the rehearsal and target.

Frequently asked questions

Can I just change REDIS_HOST?

Only if the destination is ready and the relevant state can safely be rebuilt or has already been transferred. Check URL-based overrides and every process using the connection.

Can Valkey load my Redis 7.4 dump?

The official migration guide says Redis CE 7.4-and-later data files are incompatible. Use a separately validated migration route; do not follow the compatible 7.2 physical-copy recipe.

Will all users stay signed in?

That is not guaranteed. Session bytes, expiry, client serialization and application cookie/encryption settings all matter. Test the actual application and define the accepted reset risk.

Does stopping workers make the queue safe to copy?

No. Producers can still enqueue jobs, reserved work may be executing and delayed jobs may remain. Coordinate all writers and preserve the queue's complete required state.

Sources

Related tutorials

Browse all articles
Tutorials9 min read

Serverless Webhooks with a Durable PostgreSQL Inbox

Build a serverless webhook receiver that authenticates requests, saves events before acknowledging them, and processes a durable PostgreSQL inbox safely.

Adrian Silaghi0 views

Ready to get started?

Deploy your infrastructure in minutes with DanubeData's managed services.