The five most common
- Query multiplication — lazy loading in loops
- Record-level permissions missing — action checked, ownership not
- Debug left on in production
- Email through the default backend, silently not arriving
- No tests around the business rules and permissions
The second is the most serious. A user permitted to view orders viewing someone else's order is a data breach, and it is depressingly common.
Five more
- Business logic in views, so it cannot be reused or tested
- Fat models with everything in save methods, so ordering matters and nothing is clear
- Secrets in settings committed to the repository
- Media served from the code directory
- Migrations edited after being applied somewhere
Costs
| Mistake | Typical cost |
|---|---|
| Query multiplication | Pages that take ten seconds |
| Missing record permissions | A data breach |
| Debug in production | Full exposure of settings and queries |
| Default email backend | Months of lost enquiries |
| No tests | Changes take three times as long |
All fixable without a rewrite
Every one of these is addressable incrementally in an existing application. None requires replacement, which is worth knowing before anyone proposes one.
Fix the permissions and the production settings first — those are the ones with the most serious consequences.
How to find them
- Run Django's deployment check — seconds, catches configuration
- Log query counts per page — finds multiplication immediately
- Try to access another user's record — finds permission gaps
- Send yourself an email from production — checks delivery
- Look for tests around the calculations — usually absent