To rotate a Django SECRET_KEY, put the new value in SECRET_KEY and move the old value to the front of SECRET_KEY_FALLBACKS. Django signs with the new key but still accepts data signed with the old one. When you are ready to expire old sessions and tokens, remove the old key from the list.
What the key actually protects
Django's settings reference says the secret key is used for cryptographic signing and lists what depends on it: sessions (unless you use the cache session backend), cookie-based messages, password reset tokens, and anything else that uses Django's signing tools without its own key. It also warns that running with a known key "defeats many of Django's security protections" and can lead to privilege escalation and remote code execution.
One detail trips people up. The key is not used for stored user passwords, so rotating it does not touch password hashes. Users keep their passwords. What they lose, if you rotate carelessly, is their login session and any pending reset links.
When to rotate
Rotate on a schedule you can defend, and immediately if the key may have been exposed. Common exposure paths are a settings file committed to a repository, a key pasted into a ticket or chat, a leaked backup, or a former contractor's access. If the key appeared in a public repository, treat it as burned even if you removed it in the next commit, because history and forks keep it.
The rotation steps
- Generate a new long random value with a cryptographic source, for example
python -c "import secrets; print(secrets.token_urlsafe(64))". - Store it in your secret manager or environment, never in source control.
- Set SECRET_KEY to the new value and put the old one in SECRET_KEY_FALLBACKS.
- Deploy to every instance at the same time, or at least make sure every instance has both values before any instance starts signing with the new one.
- Wait for the period you want old sessions to stay valid.
- Remove the old key from the list and deploy again.
The Django deployment checklist shows the pattern with two environment variables:
import os
SECRET_KEY = os.environ["CURRENT_SECRET_KEY"]
SECRET_KEY_FALLBACKS = [
os.environ["OLD_SECRET_KEY"],
]
What happens at each stage
| Stage | New signatures use | Old sessions and tokens |
|---|---|---|
| Before rotation | Old key | Valid |
| After step 4 | New key | Still valid, checked against fallbacks |
| After step 6 | New key | Invalid, users sign in again |
The docs note that signing checks are computationally expensive, and every fallback adds overhead to checks that do not match an earlier key. Keep the list short and remove entries promptly. The checklist says the same: remove old keys in a timely manner.
If the key leaked, the fallback is not a fix
Here is the catch. Fallback keys are still valid for verification. If an attacker holds the old key, they can keep forging signed data for as long as it sits in SECRET_KEY_FALLBACKS. For a suspected compromise, rotate with no fallback at all and accept that everyone signs in again. A forced re-login is cheaper than leaving a forging key active. Also check whether any session data was pickled, since a leaked key plus a pickle serializer is a code execution path. Django's session docs describe exactly that scenario.
Try it yourself
Click through it at your own pace, or open it full screen. Look for how a hardcoded secret in source shows up as a finding you can fix before it ships.
Quick check
Does rotating SECRET_KEY reset user passwords?
No. Django's settings reference says secret keys are not used for user passwords, so rotation does not affect them. It invalidates sessions, reset tokens and other signed data once the old key leaves the fallback list.
How many fallback keys should I keep?
As few as possible, usually one, for as short a time as your session lifetime allows. Each extra key adds signing overhead and keeps an old forging key alive.
Should I use fallbacks after a leak?
No. Fallback keys still verify signed data, so a leaked key stays useful to an attacker. Rotate without a fallback and accept the forced sign out.
Safeguard's SBOM and dependency scanning and compliance evidence automation can help you confirm which Django versions you run and keep a record of the change. You can try a free scan on a repository.
Sources
- Django settings reference, SECRET_KEY and SECRET_KEY_FALLBACKS
- Django deployment checklist
- Django cryptographic signing
- Django sessions
Last reviewed: 19 October 2026.