Django deprecates a feature over at least two feature releases: it keeps working and raises a warning, then it is removed. LTS releases get security fixes for about three years. To move between LTS versions safely, fix every warning on the old LTS, then step to the next.
The policy in plain words
The Django release process page lays out a predictable cycle. A feature deprecated in release A.x keeps working in every A.x version but raises warnings. It is removed in a later release, with a minimum of two feature releases between deprecation and removal. The page gives a worked example: a function deprecated in 4.2 raises a RemovedInDjango51Warning in 4.2, still exists in 5.0, and is gone in 5.1.
Version numbers follow a loose form of semantic versioning. Each release after an LTS bumps to the next dot zero, so you see 4.2 (LTS), 5.0, 5.1, 5.2 (LTS). Long-term support releases get security and data loss fixes for a guaranteed period, typically three years, according to the same page.
There is one detail that surprises people. Deprecations started in an LTS release are dropped in a non-dot-zero release, to honor the rule of keeping shims for at least two feature releases. The page says third party apps need to maintain compatibility back to the earlier LTS to ease LTS to LTS upgrades.
What this means for your plan
If you run an LTS and want the next LTS, you have two routes.
| Route | How it works | Trade-off |
|---|---|---|
| Jump LTS to LTS | Fix all warnings on the current LTS, then move straight to the next LTS | Fewer upgrade events, but a larger change set |
| Step through every feature release | Upgrade one release at a time | Smaller steps, more frequent work, shorter support on each stop |
The deprecation policy is what makes the jump possible. If your code runs on the old LTS with no deprecation warnings, the shims you depended on are not needed by the next LTS.
Steps for an LTS to LTS upgrade
- Confirm the current support status of your version and your target on the official download page, since dates shift.
- On the current LTS, run your tests with warnings visible. Django says the warnings are silent by default and can be shown with Python's development warning option.
python -Wd manage.py test
- Fix warnings in your own code first. Then upgrade third party packages to releases that declare support for the target version.
- Upgrade packages that your project depends on before the framework, where they are compatible with both versions.
- Move to the target LTS on a branch, run migrations on a copy of production data, and run the full suite.
- Release behind your normal staging soak.
Security reasons not to wait
Support windows end. An unsupported release stops receiving security fixes from the project. If you are past the window, an upgrade is no longer a convenience. Plan it as a risk item with an owner and a date, and record the exception if you must run unsupported for a while.
Quick check
Do deprecation warnings appear by default in Django?
No. They are silent by default and appear when you enable Python warnings in your test run.
Can I skip from one LTS directly to the next?
The policy is designed to allow it, as long as your code is clean of deprecation warnings on the older LTS and your packages support the target.
Safeguard maps your dependency inventory and flags end of support components, and a free scan is available at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.