The Five Pillars of Minimum Viable Compliance
1. Know Where PII Lives
Before you can protect or delete data, you need to know where it is.
SELECT pgcomply.quick_setup();
-- Scans all tables, detects PII patterns, creates registry
2. Delete on Request
When user-123 asks for deletion:
SELECT pgcomply.forget('user-123');
SELECT * FROM pgcomply.verify_forget('user-123');
3. Prove You Did It
The audit trail logs every compliance operation:
SELECT * FROM pgcomply.audit_log WHERE event_type = 'forget_complete';
4. Protect from Unauthorized Access
-- Mask PII for non-admin roles
SELECT pgcomply.mask('users', 'email', 'partial', ARRAY['postgres']);
-- Enable RLS on PII tables
SELECT pgcomply.enable_rls('users', 'user_id');
5. Clean Up Old Data
SELECT pgcomply.retain('sessions', 'created_at', '30 days');
SELECT pgcomply.schedule_jobs(install := true);
When to Level Up
| Stage | Users | Add | |-------|-------|-----| | Pre-seed | < 100 | quick_setup(), forget() | | Seed | 100 - 1k | Masking, retention policies | | Series A | 1k - 10k | Consent tracking, health checks | | Series B | 10k+ | Pro dashboard, access reviews, SOC 2 evidence |
Real-World Scenario: Your First DSAR
It's Tuesday morning. You receive an email: "I'd like a copy of all my personal data and then I'd like it deleted. — Jane, jane@example.com"
Without pgcomply, this triggers a fire drill: which tables have Jane's data? How do you export it? How do you delete it without breaking foreign keys? Can you prove you did it?
With pgcomply, it's three commands:
-- 1. Find all of Jane's data
SELECT pgcomply.inspect('jane@example.com');
-- 2. Export for data portability (Article 20)
SELECT pgcomply.export_user_data('jane@example.com', 'json');
-- Send this JSON to Jane
-- 3. Delete everything (Article 17)
SELECT pgcomply.forget('jane@example.com');
-- 4. Prove it's gone
SELECT * FROM pgcomply.verify_forget('jane@example.com');
Total time: under 30 seconds. Without automation, this takes 1-4 hours per request, and you'll miss a table.
The B2B Sales Question
Enterprise customers will ask about your data handling before signing. Common questions during sales due diligence:
| Question | Without pgcomply | With pgcomply |
|----------|-----------------|---------------|
| "Can you delete our data on termination?" | "We think so, let me check with engineering" | SELECT pgcomply.forget('tenant-xyz'); — done, verified, audited |
| "Where is our PII stored?" | "Let me ask the team" | SELECT * FROM pgcomply.classification_map(); — full inventory |
| "Do you have an audit trail?" | "We have application logs" | SELECT pgcomply.verify_audit(); — cryptographically verified |
| "How do you handle breach notification?" | "We'd figure it out" | SELECT pgcomply.report_breach(...) — structured process |
These answers close deals. Vague answers lose them.
Integrating with Your Stack
Next.js / Node.js
// api/gdpr/delete/route.ts
import { pool } from '@/lib/db';
export async function POST(req: Request) {
const { userId } = await req.json();
// Export before deletion (keep copy for 30 days)
const exportResult = await pool.query(
'SELECT pgcomply.export_user_data($1, $2)', [userId, 'json']
);
// Delete all PII
await pool.query('SELECT pgcomply.forget($1)', [userId]);
// Verify
const verify = await pool.query(
'SELECT * FROM pgcomply.verify_forget($1)', [userId]
);
return Response.json({ deleted: true, verification: verify.rows });
}
Django / Python
# views.py
from django.db import connection
def handle_deletion_request(request, user_id):
with connection.cursor() as cursor:
cursor.execute("SELECT pgcomply.forget(%s)", [user_id])
cursor.execute("SELECT * FROM pgcomply.verify_forget(%s)", [user_id])
verification = cursor.fetchall()
return JsonResponse({'deleted': True, 'verified': len(verification) == 0})
Summary
Start with quick_setup() on day one. It takes 2 seconds and gives you the five pillars. Then add masking, consent, and monitoring as you grow. Compliance scales with your product — do not over-engineer it at the start, but do not ignore it either.