Personal Data Map: find every column a GDPR subject access request has to reach

Reads a migration, Prisma schema, Django model or TypeORM entity and marks every column a subject access request has to reach - with the GDPR article each finding hangs on. 13 rules, line numbers, no account.

Get the complete version $29

This page is the working piece. The full pack has everything below.

Reads a migration, Prisma schema, Django model or TypeORM entity and marks every column a subject access request has to reach - with the GDPR article each finding hangs on. 13 rules, line nu

An independent EU privacy consultant bills EUR 100-200/hour (market average about EUR 150) and one manual DSAR averages about $1,524 in staff time across 8-12 hours.

Buy the full version — $29
Want the full version?
Enter your email and we send the download link.
ENDEJAESPT

Find a tool

· ReadyStack

Worked example

Real numbers from this tool, line by line.

Five columns in one migration will break your next subject access request

Five columns in a thirty-line Postgres migration will break the next subject access request a Berlin SaaS team receives, and the worst of them is a copy table nobody remembers creating.

Here is the migration. Nothing in it is unusual; every line of it has been written by a careful engineer.

CREATE TABLE users (
  id                 BIGSERIAL PRIMARY KEY,
  email              VARCHAR(255) NOT NULL UNIQUE,
  date_of_birth      DATE,
  national_id        VARCHAR(20),
  password           VARCHAR(72) NOT NULL,
  ip_address         INET,
  stripe_customer_id VARCHAR(40),
  is_deleted         BOOLEAN DEFAULT false
);

CREATE TABLE health_records (
  user_id   BIGINT REFERENCES users(id),
  diagnosis TEXT,
  notes     TEXT
);

CREATE TABLE users_audit (
  user_id    BIGINT,
  email      VARCHAR(255),
  iban       VARCHAR(34)
);

Under Art. 12(3) you have one month from the request, extendable by two more only if you tell the person why inside that first month. Here is what that month runs into.

password is stored under a plain name. Art. 32 asks for state-of-the-art protection, and an Art. 15 export must never return it. Rename it to password_hash and store a derived value.

diagnosis is Art. 9 special-category data. It needs an Art. 9(2) condition sitting on top of your Art. 6 basis, and it pushes the table over the Art. 35 DPIA threshold.

CREATE TABLE users_audit is the expensive one. Erasure under Art. 17 and access under Art. 15 reach the copies too, and incomplete erasure is almost always found here rather than in the main table.

REFERENCES users(id) with no ON DELETE rule means the health record survives the user you just deleted. The erasure was not an erasure.

is_deleted BOOLEAN is the same failure wearing a different hat. A flag is not erasure. The row still holds the person, and read replicas still serve it. Name the hard-delete or anonymise job that follows the flag, or the flag is a promise you do not keep.

Two more the same file hides: ip_address is personal data once you can identify the user (Recital 30, and the CJEU in Breyer, C-582/14), and stripe_customer_id is proof that this person's data left for a processor who must be named in your Art. 30(1) record.

The obvious move is to paste the file into a chatbot. It reads the one table you gave it. It cannot see the other forty migrations, and it cannot see the missing ON DELETE three files away. On the law it is worse than blind: ask it about the Art. 30 record today and it will hand you the Digital Omnibus 750-employee exemption, which as of September 2026 is a proposal still under negotiation, not law you can rely on.

A manual subject access request averages about $1,524 in staff time, eight to twelve hours of it, and an independent EU privacy consultant bills EUR 100-200 an hour. The map of which columns you actually hold is the cheap part, and it should not be the part you do by reading.

Personal Data Map is a VS Code extension and a free web page that run the same thirteen rules over a schema and return line numbers with the article each finding hangs on. The free side finishes the file you have open. Paste a migration into the page and the answer is on screen before you type anything.

15 seconds — what it actually does

Questions people ask

What does Personal Data Map actually do?

It reads a database migration, Prisma schema, Django model or TypeORM entity and marks every column a GDPR request has to reach. Each finding carries the line number, the severity, and the article it hangs on: Art. 9 special category, Art. 32 credentials, Art. 17 erasure, Art. 30 records. Thirteen rules ship inside.

Who is this for?

Backend and platform engineers who own the migrations and ORM models in an EU or UK product, and who get handed the subject access request when one arrives. It is aimed at teams without a full-time privacy engineer, where the person who wrote the schema is also the person who has to answer for it.

Why is asking an AI assistant not enough?

A chatbot reads the one table you paste. It cannot see the other forty migrations, the users_audit copy table, or the missing ON DELETE three files away. On the law it is also stale: ask about the Art. 30 record and it repeats the Digital Omnibus 750-employee exemption, which in September 2026 is still a proposal under negotiation, not law.

What is free and what needs a licence?

Free runs all thirteen rules over the file you have open, or over a selection, with no account and no key: that job finishes. A licence adds a different job, not a bigger one — mapping every migration and model in the repository at once, exporting the map as CSV, JSON or HTML, and writing JSON your CI can fail on.

What does the alternative cost?

An independent EU privacy consultant bills roughly EUR 100-200 an hour, market average about EUR 150, and UK outsourced DPO work starts near GBP 150 an hour. One manual subject access request averages about $1,524 in staff time across eight to twelve hours. The licence is $29 once, with a seven-day full refund.

Ask about this tool

One question, answered by the person who built it. Your email only if you want the answer sent.