To rotate the Laravel APP_KEY without logging users out, generate a new key, set it as APP_KEY, and put the old key in APP_PREVIOUS_KEYS. Laravel encrypts with the current key and tries previous keys when decrypting, so existing sessions and encrypted data keep working during the changeover.
What the APP_KEY protects
Laravel uses APP_KEY as the encryption key behind its encrypter. Per the documentation, encrypted values use OpenSSL with AES and are signed with a message authentication code, so tampering is detected. Because Laravel encrypts every cookie, including the session cookie, the key matters for more than the Crypt facade.
If you simply replace the key, two things happen. All authenticated sessions are logged out, and any data encrypted with the old key can no longer be decrypted.
The graceful rotation
Generate the new key with the framework command, not by hand, since it uses PHP's secure random bytes generator:
php artisan key:generate --show
Then update your environment:
APP_KEY="base64:NEW_KEY_VALUE"
APP_PREVIOUS_KEYS="base64:OLD_KEY_VALUE"
The value of APP_PREVIOUS_KEYS is a comma delimited list, so you can keep several old keys. Laravel always encrypts with the current key. On decrypt it tries the current key first, then each previous key until one works.
Steps
- Decide why you are rotating: routine hygiene, or a suspected leak. The urgency differs.
- Generate a new key with
key:generate --show. - Copy the current
APP_KEYintoAPP_PREVIOUS_KEYS, appending if the variable already exists. - Deploy the new
APP_KEYto every web server and every queue worker. - Restart workers so they load the new environment.
- Re-encrypt stored data over time so it no longer depends on the old key.
- Remove the old key from
APP_PREVIOUS_KEYSonce nothing depends on it.
A leak is not a routine rotation
The graceful path keeps the old key working. That is the opposite of what you want if the old key was exposed. If an attacker holds the old key and it stays listed as a previous key, values made with it will still decrypt. In a suspected leak, plan a short window, re-encrypt stored values, then drop the old key quickly, accepting that some sessions will end.
| Situation | Approach |
|---|---|
| Scheduled rotation | Use APP_PREVIOUS_KEYS, retire old key after a set period |
| Key exposed in a repo or log | Rotate, re-encrypt, remove the old key fast, accept logouts |
| Several servers or workers | Roll out the same values everywhere before restarting |
What to check after
Sign in with a test account that was logged in before the change and confirm the session survives. Decrypt a sample of stored encrypted values. Watch your error tracker for DecryptException, which Laravel throws when a value cannot be decrypted.
Quick check
Does Laravel re-encrypt old data automatically?
The documentation describes decryption falling back to previous keys. It does not describe automatic re-encryption of stored values, so plan that step yourself.
Where should the key live?
In the environment of each server, not in version control. The Laravel configuration docs advise against committing the .env file.
Safeguard's compliance and evidence automation can help you keep a dated record of when keys were rotated. A free scan is at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.