Code Audit for a Django App: What a Developer Checks First
A Django application can work well for months and still hide problems that become expensive later. Maybe pages are getting slower, bugs keep returning, new features take longer than expected, or the developer who built the system is no longer available. You may also be considering a redesign, a new integration, or a handover to another team.
Before making major changes, it helps to understand the condition of the codebase. A Django code audit is a structured review of an application's code, security, data handling, performance, tests, and deployment setup. It helps identify risks and gives you a clearer basis for deciding what to fix first.
An audit is not simply a search for bad code or a promise that every issue will be found. It is an evidence-based assessment of the application's current state, its most important risks, and the practical steps needed to improve it.
This checklist explains what a developer typically checks first, what business owners should expect from the process, and how to use the findings to plan the next phase of work.
What Is a Django Code Audit?
A Django code audit is a technical review of a Django-based website, API, or web application. Its scope can range from a focused review of a specific problem to a broader assessment of the application and its production environment.
Depending on the project, the review may cover:
- Project structure and architecture
- Django settings and security controls
- Authentication, permissions, and sensitive data
- Database design, queries, and migrations
- Views, models, serializers, forms, and API behavior
- Automated tests and error handling
- Third-party packages and dependency maintenance
- Performance and resource usage
- Deployment, logging, backups, and operational readiness
- Documentation and handover risks
The exact scope should be agreed in advance. A small internal tool does not necessarily need the same depth of review as a healthcare platform or a high-traffic SaaS application.
1. First, Understand What the Application Does
A developer should not begin by changing code without understanding the business purpose of the application. They will usually start by reviewing the project overview, important user journeys, known issues, and the systems the application depends on.
Useful questions include:
- What are the application's most important workflows?
- Which features are currently failing or difficult to change?
- Which parts of the system handle sensitive or business-critical data?
- What external services does it depend on?
- How is it deployed, and who maintains it?
- Are there known performance, security, or reliability concerns?
This context helps the reviewer focus on risks that matter. For example, a slow report used every day by the finance team may deserve more attention than an infrequently used page with a minor layout issue.
The developer should also establish whether they can safely run the project locally or in a staging environment. Production data and live services should not be casually copied or modified during an audit.
2. Review the Project Structure and Architecture
Next, the developer looks at how the code is organised and how the main parts of the application fit together.
In a Django project, this can include:
- How Django apps are divided by business responsibility
- Whether models, views, forms, serializers, and service logic have clear roles
- Whether business rules are duplicated across multiple places
- Whether settings are organised for different environments
- Whether API endpoints and URL patterns are understandable
- Whether external services are isolated behind clear interfaces
- Whether the code has hidden dependencies or circular imports
There is no single project structure that is right for every Django application. A small project may reasonably have a simpler layout than a large multi-team platform. The concern is whether the structure makes the system understandable, testable, and safe to change.
What a business owner should look for: The audit should identify areas that make new features risky or slow, explain why they matter, and recommend improvements in proportion to the project's needs—not suggest a complete rewrite by default.
3. Check Security and Django Configuration
Security is one of the first areas to investigate, especially when the application stores personal information, financial records, business data, or user credentials.
Django provides built-in protections, but they still need to be configured and used correctly. The official Django deployment checklist covers security settings, environment-specific configuration, performance, and error reporting.
A reviewer may check the following:
- Production settings: Is
DEBUGdisabled in production, and isALLOWED_HOSTSconfigured appropriately? - Secrets: Are
SECRET_KEY, database credentials, API keys, and other secrets kept out of source control? - HTTPS and cookies: Is HTTPS enforced where required, and are secure cookie settings configured correctly?
- Authentication: Are login, logout, password reset, session, and account recovery flows implemented safely?
- Permissions: Can users access only the records and actions they are authorised to use?
- CSRF protection: Are state-changing browser requests protected where applicable?
- Input handling: Are user-controlled inputs validated, and are database queries and output handling safe?
- File uploads: Are uploaded files treated as untrusted, with appropriate type, size, storage, and access controls?
- Error messages: Do production errors avoid revealing secrets, stack traces, or sensitive implementation details?
- Dependencies: Are important packages maintained, and are known vulnerabilities assessed?
A code audit should not assume that hiding a button in the frontend is sufficient access control. The backend must enforce permissions for the relevant operations and records.
Security findings should be prioritised by realistic impact and likelihood. The OWASP Top 10:2025 provides a useful awareness framework covering areas such as broken access control, security misconfiguration, software supply-chain failures, and authentication failures. It is a starting point, not a substitute for a project-specific security assessment.
4. Examine Authentication and Role-Based Permissions
Authentication establishes who a user is; authorisation determines what that user is allowed to do. Both need attention.
A reviewer may test whether:
- Unauthenticated users can reach protected pages or API endpoints
- A regular user can view or edit another user's records by changing an identifier
- Staff and administrator roles have clearly defined permissions
- Sensitive actions require the appropriate level of access
- Permissions are enforced consistently across pages, APIs, and background tasks
- Account deactivation and password changes invalidate access where required
- Administrative access is appropriately restricted and monitored
For example, if a customer can change /orders/102/ to /orders/103/ and see another customer's order, the issue is not merely a frontend bug. It may indicate missing object-level authorisation.
The audit should document the affected workflow, the evidence, the potential impact, and a recommended remediation. Any testing against a live application should be explicitly authorised and conducted within agreed limits.
5. Review Models, Database Design, and Migrations
The database often sits at the centre of a Django application. Poor data modelling or unsafe changes can affect reliability, reporting, and the ability to introduce new features.
The developer may review:
- Model relationships and field definitions
- Required fields, uniqueness constraints, and validation
- Foreign keys and deletion behavior
- Indexes on frequently queried fields
- Duplicate or inconsistent data
- Migration history and dependencies
- Whether migrations can be applied safely in the intended environments
- Backup and restore arrangements for important data
Django model validation, database constraints, and application-level checks serve different purposes. A review should consider where important rules are enforced and whether the database protects the integrity of critical records when multiple operations happen at once.
Migrations deserve special care. A change that looks harmless in development can create locks, take a long time, or require a data migration on a large production table. The reviewer should identify high-risk migrations and recommend a safe deployment approach where needed.
Before a risky migration or data correction, confirm that suitable backups exist and that the restoration process is understood. A backup that has never been tested may not provide the protection the business expects.
6. Look for Slow Database Queries and Performance Bottlenecks
A Django application can feel slow because of database queries, external API calls, large responses, inefficient application logic, infrastructure limits, or several issues combined.
A reviewer may investigate:
- Repeated queries inside loops
- Missing or unsuitable database indexes
- N+1 query patterns
- Unnecessary retrieval of large datasets
- Expensive aggregation or filtering
- Slow external service calls
- Missing or poorly designed caching
- Large file processing inside web requests
- Long-running tasks that may belong in a background worker
Django provides tools such as select_related() and prefetch_related() to help reduce unnecessary database queries when used appropriately. But optimisation should be guided by evidence rather than applied everywhere.
Useful evidence may include query counts, timings, application logs, database statistics, and repeatable tests. A developer should distinguish measured bottlenecks from areas that only look suspicious in a code review.
What a business owner should expect: A short list of the slowest or most expensive workflows, the evidence supporting each finding, and a recommendation that explains the expected benefit and implementation risk.
7. Evaluate Tests and Error Handling
Automated tests help the team make changes with more confidence. During an audit, the reviewer may look at both the tests that exist and the critical workflows that are not covered.
Questions include:
- Are important business rules tested?
- Do tests cover successful and failed outcomes?
- Are permissions and access restrictions tested?
- Are API validation and error responses predictable?
- Do tests depend on external services in fragile ways?
- Can the test suite run reliably in a clean environment?
- Are recurring production bugs covered by regression tests?
A high test count does not automatically mean an application is reliable. Tests need to verify meaningful behavior, and important workflows may still be untested.
The review should also inspect error handling and logging. Users need clear, safe messages, while maintainers need enough diagnostic information to investigate failures. Sensitive data should not be written into logs unnecessarily.
If the application has no useful test suite, the recommendation may be to establish coverage around the most critical workflows first rather than attempt to test the entire codebase at once.
8. Inspect Dependencies and Third-Party Integrations
Django projects commonly rely on packages for APIs, authentication, background jobs, payments, reporting, storage, and other features. External services introduce additional failure points.
The developer may check:
- Whether dependency versions are recorded consistently
- Whether packages are actively maintained
- Whether known vulnerabilities affect the installed versions
- Whether upgrades have been delayed for important reasons
- Whether credentials and configuration are stored safely
- What happens when an external service times out or becomes unavailable
- Whether retries can create duplicate operations
- Whether webhooks are authenticated and handled safely
Upgrading every package to the newest version during an audit is not always appropriate. The reviewer should identify relevant risks, compatibility concerns, and a sensible upgrade plan.
For critical integrations, consider idempotency, retry limits, timeout handling, monitoring, and recovery procedures. For example, retrying a payment request without checking whether the first attempt succeeded could create a duplicate charge if the integration is not designed carefully.
9. Check Deployment, Monitoring, and Backups
Code quality is only part of an application's condition. A project may behave correctly on a developer's machine but fail in production because of configuration, infrastructure, or deployment issues.
A deployment review may include:
- Separation of development, staging, and production settings
- Environment variables and secret management
- Static and uploaded media file handling
- Database connection and access configuration
- HTTPS and relevant security headers
- Process management and background workers
- Logging, error reporting, and monitoring
- Deployment and rollback procedures
- Database and media backups
- Evidence that recovery procedures have been tested
Django's official deployment checklist recommends reviewing security, environment-specific settings, performance, and error reporting before deployment. The exact controls depend on the infrastructure and the application's risk profile.
A reviewer should not make production changes without approval, a suitable rollback plan, and an understanding of the impact. An audit is meant to reduce risk, not introduce avoidable downtime.
10. Assess Maintainability and Handover Readiness
Sometimes the most urgent issue is not a visible bug. It is the fact that only one developer understands how the system works.
A reviewer may check whether:
- Setup instructions are accurate
- Required environment variables are documented
- The team understands how to run tests and migrations
- Important business rules are explained
- Deployment steps are documented
- External services and their owners are listed
- Known limitations and technical debt are recorded
- Code ownership and access to repositories or infrastructure are clear
Documentation does not need to explain every line of code. It should help a qualified developer set up the project, understand the main workflows, investigate issues, and deploy changes safely.
If you are taking over an existing application, this review can be especially valuable. It can reveal missing access, undocumented services, fragile deployment steps, and areas where knowledge is concentrated in one person's head.
Django Code Audit Checklist
Use this checklist to structure an initial review. It is not a guarantee of security or correctness, and each item should be assessed in the context of the actual application.
Code and architecture
- Project structure and major workflows are understood.
- Business logic is organised clearly enough to maintain.
- Important settings are separated appropriately by environment.
- Duplicated logic and tightly coupled components are identified.
Security and access
- Production settings are reviewed.
- Secrets are not committed to the repository.
- HTTPS, cookies, and session settings are appropriate.
- Authentication and password recovery flows are reviewed.
- Object-level and role-based permissions are tested.
- User input and file uploads are handled safely.
- Relevant dependencies are checked for known vulnerabilities.
Database and performance
- Models, constraints, and relationships are reviewed.
- Migration history and risky changes are assessed.
- Slow queries and repeated database access are investigated.
- Indexes and data volume are considered.
- Backups and restoration procedures are reviewed.
Tests and operations
- Critical workflows have meaningful tests.
- Error handling and logging are useful and safe.
- External service failures are handled predictably.
- Deployment and rollback steps are documented.
- Monitoring and error reporting are configured.
- Setup instructions and handover documentation are current.
What Should You Receive After a Code Audit?
A useful audit should produce more than a verbal statement that the code is “good” or “bad.” Ask for findings that help you make decisions.
A practical deliverable may include:
- Executive summary: The overall condition of the application in plain language.
- Prioritised findings: Issues grouped by severity, business impact, and urgency.
- Evidence: Relevant files, workflows, logs, test results, or examples that support the findings.
- Recommended actions: What should be fixed, why it matters, and the likely dependencies.
- Scope and limitations: What was reviewed, what was not reviewed, and which environments were available.
- Next-step plan: A suggested order for remediation, further testing, or deeper specialist review.
You can ask the developer to separate immediate risks from improvements that can wait. For example, a broken permission check may need urgent attention, while a small refactor may be scheduled alongside future feature work.
Avoid treating an audit as a guarantee that no bugs or vulnerabilities remain. The quality of the conclusion depends on the scope, access, evidence, and methods used. A code review alone cannot prove that a complex application is completely secure.
How Much Does a Django Code Audit Cost?
The cost depends on the size and condition of the application, the depth of review, the availability of documentation and tests, and whether the audit includes live testing, performance profiling, infrastructure review, or a remediation plan.
A focused review of one feature is different from an audit of a multi-tenant SaaS platform with several integrations and sensitive data. Rather than relying on a generic price, ask for a scoped proposal that specifies:
- Which applications, repositories, and environments are included
- Which security, performance, and code-quality checks will be performed
- Whether the work includes automated tools, manual review, or both
- What access and documentation you need to provide
- Which deliverables you will receive
- Whether fixes are included or quoted separately
- How findings will be prioritised and verified
Separating the audit from remediation can help you understand the issues before committing to a larger development project. It also gives you a clearer way to compare proposals.
When Should You Request a Django Code Audit?
Consider an audit when:
- You are taking over a project from another developer.
- The application has recurring bugs or unexplained slowdowns.
- You are planning a major feature, integration, or database change.
- You need to assess security and maintenance risks before expanding the product.
- The team lacks reliable tests or deployment documentation.
- You are preparing for a technical handover or evaluating an inherited codebase.
- You need a prioritised plan for technical debt instead of fixing issues reactively.
You do not need to wait until the application fails. Reviewing the code before a major investment can help reveal dependencies and risks while there is still time to plan around them.
Final Thoughts
A Django code audit should help you answer three practical questions: what condition is the application in, which risks matter most, and what should happen next?
The first checks usually focus on understanding the business workflows, reviewing architecture and settings, assessing access controls, examining data handling, and looking for evidence of performance or reliability problems. From there, the scope can expand into tests, integrations, deployment, and handover readiness based on the project's needs.
If you own a Django application and need a clearer picture before adding features, changing developers, or improving reliability, get in touch to discuss an audit scope and the outcomes you need.