Django Privacy and GDPR Production Checklist

A technical privacy checklist for Django in production: personal data inventory, logs and error tracking, cookies, retention and deletion including backups, exports, encryption, access control, and processors.

Problem statement

A Django app that handles users' names, emails, addresses, or payment details holds personal data, and in the EU and many other jurisdictions that brings obligations: collect only what you need, protect it, keep it only as long as necessary, let people access and delete it, and know who else processes it. Most of the effort is technical, and much of it lives in deployment and operations rather than models: logs, error trackers, backups, analytics, and third-party services.

This checklist covers the technical side for a production Django deployment. It is not legal advice; your privacy policy, legal bases, and contracts need review by someone qualified. It helps you find where personal data actually flows so those decisions are based on facts.

Where personal data spreadsDatabasemodels and fieldsLogs and tracesIPs, emails, bodiesBackupscopies for monthsThird partiesemail, analyticsDeleting a user in the database is not enough; logs, backups, and processors hold copies too.
  1. Inventory personal data: models and fields, uploaded files, logs, error reports, analytics, backups, and third-party services.
  2. Keep personal data out of logs and error trackers where possible (no request bodies, no passwords, minimal identifiers).
  3. Use only essential cookies without consent; gate analytics and marketing cookies behind consent.
  4. Define retention per data type and enforce it with scheduled jobs, including sessions, logs, and backups.
  5. Implement data export and deletion as tested code paths, and document how deletion interacts with backups.
  6. Encrypt in transit everywhere and at rest where the platform allows; restrict and audit access.
  7. List your processors (hosting, email, error tracking), their regions, and data processing agreements.

Checklist

1. Data inventory

  • Models and fields containing personal data are listed, with the purpose of each (for example "email: login and transactional mail").
  • Free-text fields that may contain personal data (notes, messages, support tickets) are included.
  • Uploaded files (avatars, documents, ID scans) are listed with their storage location.
  • Data you do not need is not collected, or is removed.
personal data is not only in the databaseTypical personal dataDeletion reaches it?Databaseaccounts, orders, messages✓yesLogsIPs, emails in URLs!only by retentionError trackerrequest data, user IDs!only by retentionBackupseverything, frozen!when backups expireEmail provideraddresses, message logs✕separate requestThe inventory is what makes deletion and export answerabledjango-deployment.com
Record retention periods for every row; they are part of the privacy notice.

A quick way to start the list:

from django.apps import apps

for model in apps.get_models():
    fields = [f.name for f in model._meta.get_fields() if getattr(f, "concrete", False)]
    print(model._meta.label, fields)

2. Logs

  • Access logs: decide whether full IP addresses are needed; shorten or anonymise them in Nginx logs if not, and set retention.
  • Application logs do not contain passwords, tokens, full request bodies, or payment data; log user IDs rather than emails where possible.
  • django.request error logs and AdminEmailHandler emails can include request data; error emails are often better replaced by an error tracker with scrubbing.
  • Log retention is defined (for example 14 to 30 days) and enforced by rotation and in central log storage.
logs that are still useful without namesPersonal data in logs✕emails in query strings✕full request bodies✕kept foreverPseudonymised✓user ID instead of email✓IP truncated or dropped✓retention of 14 to 30 daysKeep personal data out of URLs so access logs stay cleandjango-deployment.com
A user ID is still personal data, but it can be deleted with the account.

3. Error tracking and monitoring

  • Error tracker SDKs do not send personal data by default; for Sentry, keep send_default_pii=False unless you have a reason and a legal basis.
  • Server-side scrubbing rules remove sensitive fields (passwords, tokens, card data, emails) from events.
  • Retention in the error tracker and APM is set to what you need.

4. Cookies and tracking

  • Django's session and CSRF cookies are strictly necessary for the site to work; document them.
  • Analytics, advertising, and third-party embed cookies are only set after consent where required, and the consent mechanism actually blocks scripts before consent.
  • Cookie flags are set: SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE, HttpOnly, and SameSite.

5. Retention and deletion

  • Retention periods exist per data type (accounts, orders, logs, support messages, backups) and match your privacy policy.
  • Expired sessions are cleared (clearsessions on a schedule).
  • Inactive accounts and old records are deleted or anonymised by scheduled jobs, not by hand.
  • Account deletion removes or anonymises the user's data across related models, uploaded files, and caches.
  • Deletion requests are propagated to processors that hold copies (email service contact lists, CRM, analytics).
  • Backups: you have a documented approach, typically letting backups expire on their normal schedule and re-applying deletions if a backup is ever restored.
deletion takes effect in stagesDeletion requestedday 0Account deactivatedimmediatelyRows deletedafter a grace periodLogs roll offretention windowBackups expiree.g. day 35Tell users the longest of these windows, not the shortestdjango-deployment.com
Restoring a backup must re-apply deletions that happened after it was taken.

6. Access and export

  • Users can obtain a copy of their data, or staff can produce it with a tested management command in a machine-readable format (JSON or CSV).
  • Staff access to personal data in the admin follows least privilege: permissions and groups limit who sees what.
  • Admin access is logged (Django's LogEntry records changes; consider logging views of sensitive records too).
  • Production database access for developers is limited, audited, and not the default way of working.
answering an access request1Verify identitylogged-in session or proof2Collect from the inventoryevery system listed3Export as JSON or CSVa management command4Deliver securelyexpiring link5Record the requestdate and what was sentA scripted export turns a week of work into minutesdjango-deployment.com
The same command is a good test that the inventory is complete.

7. Security of processing

  • HTTPS everywhere, with HSTS; internal connections to the database and cache use TLS when they cross networks you do not control.
  • Disks, databases, and object storage are encrypted at rest where the platform offers it.
  • Passwords use Django's default hashers; no custom or weakened hashing.
  • Secrets are stored outside the repository; access to them is limited.
  • Non-production environments do not contain real personal data, or use sanitised copies.

8. Processors and locations

  • Every service receiving personal data is listed: hosting, database, backups, email delivery, error tracking, analytics, support tools.
  • For each: data processed, region, data processing agreement, and transfer mechanism if data leaves your required region.
  • Hosting regions are chosen deliberately (for example EU regions for an EU user base, if required).

9. Incidents

  • There is a documented process for personal data breaches: detection, assessment, who decides on notification, and time limits.
  • Logs and audit trails are sufficient to determine what data was affected.

Explanation

Privacy regulation asks what you store, why, for how long, who can see it, and whether you can hand it over or delete it on request. In a Django deployment, the database answers only part of that. Personal data also flows into access logs, error reports, caches, backups, search indexes, and third-party services, each with its own retention and access rules. A technical inventory plus enforced retention and tested export and deletion paths make the legal commitments something the system actually does.

Edge cases / notes

Anonymisation versus deletion

Keeping order records for accounting while removing personal details is common: replace names and addresses with placeholders and unlink the user, but keep amounts and dates. Make sure anonymised records cannot be re-identified through other fields.

Search indexes and caches

External search indexes (Elasticsearch, OpenSearch) and caches hold copies. Deletion code should remove documents from indexes and invalidate cached pages or fragments containing the data.

When to automate this

Turn retention into scheduled management commands, deletion and export into tested code paths with a single entry point, and the inventory into a checked-in document updated in code review when models change. Automation is what keeps privacy promises true after the team changes.

Next steps

FAQ

Is this checklist enough to be GDPR compliant?

No. It covers technical measures. Legal bases, privacy notices, contracts, and records of processing need review by someone qualified.

They are generally considered strictly necessary for the site to function. Analytics and marketing cookies usually require consent in the EU.

How do I handle deletion requests with backups?

Common practice is to let backups expire on their normal schedule and re-apply deletions if a backup is restored. Document the approach.

Should error trackers receive user emails and IP addresses?

Only if needed and justified. Default to sending no personal data and scrub sensitive fields.

Keep going