You ship your SaaS, a European user signs up, and six months later you get an email: "Please delete all my data."
If you haven't built anything for this, you're about to spend an afternoon manually combing your database. Or you're about to pay $79/month for a compliance tool you don't really understand.
GDPR has four requirements that affect every SaaS selling to EU customers:
Most of this is simpler to implement than the compliance industry wants you to think. Here is what you actually need to build, and how the Next.js SaaS Boilerplate makes each one faster.
The GDPR rule is not "show a banner." It is "don't set non-essential cookies before consent."
Essential cookies -- session auth, CSRF tokens, the user's current language -- are fine without consent. What needs consent: analytics pixels, third-party marketing scripts, anything that tracks users across sites.
If your SaaS uses Vercel Analytics (which the boilerplate already wires up), you're in good shape -- Vercel Analytics is privacy-friendly and does not set tracking cookies. You still need a consent mechanism if you add Google Analytics, Meta Pixel, or similar scripts.
The minimum viable approach:
consent cookieYou do not need a $100/month tool for this. A React component that reads a consent cookie and conditionally renders a <Script> tag is the entire implementation. The component goes in components/layout/ and gets mounted in your root layout.
GDPR Article 20 gives users the right to receive their personal data in a portable format -- typically a JSON or CSV download.
The practical implementation in a Next.js SaaS:
GET /api/users/me/export route that requires auth// app/api/users/me/export/route.ts
export async function GET(req: Request) {
const user = await getUserFromRequest(req); // throws 401 if not authenticated
const data = await userService.exportUserData(user.id);
return new Response(JSON.stringify(data, null, 2), {
headers: {
'Content-Type': 'application/json',
'Content-Disposition': 'attachment; filename="my-data.json"',
},
});
}
The exportUserData service method queries all relevant tables using Drizzle ORM and assembles the result. If you followed the module architecture, each feature module owns its own table -- your export service calls each module's repo to gather the user's records.
When a user requests deletion, you have 30 days to comply. What deletion means in practice:
[deleted] on payment records, keep the transaction amount for tax purposes)The flow that works:
With Drizzle ORM and cascading deletes configured in your schema, the database handles most cleanup automatically. Set onDelete: 'cascade' on foreign keys pointing to the users table:
// In your module schema files:
authorId: uuid('author_id')
.notNull()
.references(() => userTable.id, { onDelete: 'cascade' }),
The one piece you handle manually is anonymizing financial records -- swap PII fields to [deleted] in the same transaction before removing the user row.
You need one. It does not have to be a 10,000-word legal document.
A credible privacy policy for a small SaaS covers:
A lawyer-reviewed template costs $50-200 as a one-time purchase. Termly and Iubenda generate them automatically from a questionnaire. Get one before you launch -- it takes an hour.
The auth layer (getUserFromRequest), the user settings page scaffold, and the module architecture with Drizzle ORM are already in place when you start from the Next.js SaaS Boilerplate.
The consent banner, export endpoint, and deletion flow are the three additions you build on top. Total build time for a working GDPR setup: half a day.
Ship your GDPR checklist before your first EU customer asks for it -- it is much easier to build proactively than to scramble under a deadline.