Compliance
SOC 2 · GDPR · Drata/Vanta · Encryption · Audit
Compliance is the door to mid-market and enterprise deals — it's not optional past ~$1M ARR. The good news: SOC 2 Type II and GDPR overlap heavily, and most controls are engineering hygiene (encryption, audit logs, access controls) that you'd want anyway. Lean on a compliance platform (Drata or Vanta) to collect evidence and run the audit; spend engineering time on the actual controls, not on filling out a hundred Excel sheets.
Primary stack
The default picks this pillar assumes
- Drata~$7-15k/year
Alternates worth knowing
Swap in when scale, cost or constraints change
- Vanta
- Secureframe
Threat Model
A written document: who are the attackers, what are they after, what's the impact, what controls block them. Living doc, reviewed quarterly. Without one, every control is theater.
How it flows
step by step- 01step
STRIDE per system (Spoofing, Tampering, Repudiation, Info disclosure, DoS, Elevation).
- 02step
Per asset: 'customer data', 'auth credentials', 'billing info' — rank by impact + likelihood.
- 03step
For top 10: map to existing controls + gaps.
- 04step
Gap → ticket → quarterly closeout.
Cases & edge cases
watch for theseDon't try to defend against everything — pick the actual threats (account takeover, leaked DB dump, malicious admin).
Insider threat is the unspoken big one for SaaS — least-privilege your team early.
Review after every major architecture change.
Checklist
ship readiness- must
Documented threat model committed to repo
- should
Quarterly review on the calendar
Encryption
TLS everywhere in transit (handled by Cloudflare + Vercel). Postgres at rest (managed providers do this by default). Field-level encryption for the few sensitive columns (e.g. API keys, sensitive PII) using a KMS-wrapped key.
How it flows
step by step- 01step
TLS 1.3 enforced edge → origin (Cloudflare strict mode + Vercel).
- 02step
Postgres at rest via provider (Supabase/Neon — verify in their compliance docs).
- 03step
Sensitive fields: encrypted with aes-256-gcm, key wrapped by AWS KMS / Google Cloud KMS.
- 04step
Backups encrypted with a different KMS key (segregation of duty).
Cases & edge cases
watch for theseField-level encryption breaks LIKE / index queries — only encrypt fields you'd never query in full text.
Rotate KMS keys annually; re-encrypt during a maintenance window.
Master key is in KMS, NEVER in env vars. Env contains the KMS key ID + IAM role.
Checklist
ship readiness- must
TLS 1.2+ enforced everywhere
- must
Postgres encrypted at rest (verify)
- must
Sensitive fields encrypted with KMS-wrapped key
- should
Annual key rotation runbook
Where it lives
code references- lib/crypto/field-encryption.ts
Audit Logs
Append-only audit table that captures actor, action, target, before/after, ip, user_agent, request_id. Required for SOC 2 CC7; valuable for customer-facing 'activity log' surfaces too.
How it flows
step by step- 01step
Every mutating action (server action, admin op, webhook) emits an audit event.
- 02step
Stored in a partitioned-by-month table; tamper-evident (hash chain or external WORM).
- 03step
Customer-facing view shows their org's events in /settings/activity.
- 04step
Auditor export: SOC 2 sample requests come from here — JSON export with filters.
Cases & edge cases
watch for theseNever UPDATE / DELETE audit rows. Even retention deletes happen via tombstones.
Admin / impersonation actions are the highest-stakes — flag them clearly in the log.
Retention: 12 months minimum for SOC 2; 24+ for finance customers.
Where it lives
code references- drizzle/schema/audit-log.ts
- lib/audit/log.ts
Access Controls
Internal access to prod is gated: MFA required, role-based access, time-bound credentials. No shared accounts. Production DB access via a bastion / SSO-gated tool, with every query logged.
How it flows
step by step- 01step
Identity provider for the team: Google Workspace / Okta with MFA enforced.
- 02step
Cloud / vendor access via SSO + role mapping; no individual passwords.
- 03step
Prod DB access: zero standing access; request via PR / Slack with auto-expiring credentials (Teleport / SymOps).
- 04step
On-call gets temporary higher access; revoked after shift.
Cases & edge cases
watch for theseQuarterly access review: every role, every member — still needed?
Offboarding within hours (ideally minutes) of departure — SCIM helps.
Service accounts have rotated credentials, no humans share them.
Checklist
ship readiness- must
MFA enforced on all internal tools
- must
SSO for vendor consoles
- should
Zero-standing prod DB access
- must
Quarterly access review
GDPR / Data Subject Rights
EU users can request: a copy of their data (access), deletion (erasure), correction (rectification), portability (machine-readable export). 30-day response deadline. Build the tooling once; service requests within minutes.
How it flows
step by step- 01step
User submits request via /privacy or email to dpo@.
- 02step
Automated identity verification (sign in + confirm via email).
- 03step
Job runs: collect data across systems (DB, Stripe, Sentry, PostHog, mailing list).
- 04step
Bundles JSON + CSV → emails secure download link.
- 05step
Erasure: scrubs PII (replace with hash), keeps row for billing/auditing, then full delete after retention period.
Cases & edge cases
watch for theseErasure doesn't always mean DELETE — billing/audit rows may need to retain hashed actor IDs.
Third-party processors (Stripe, PostHog, Sentry) need to honor erasure too — wire their APIs.
Track DSR (Data Subject Request) tickets — auditors will ask.
Checklist
ship readiness- must
Self-serve DSR portal
- must
Erasure scripted across all systems (incl. third parties)
- must
DSR ticket log retained
Where it lives
code references- app/privacy/page.tsx
- lib/privacy/dsr.ts
Data Residency
Some customers (EU, healthcare, defense) require data to stay in their region. Architectures: multi-region with tenant pinning, or fully separate deployments per region. The harder you commit, the bigger the contract.
How it flows
step by step- 01step
On sign-up, customer picks region (or it's inferred from IP for self-serve).
- 02step
Tenant pinned to a region-specific DB cluster.
- 03step
App routes requests to the right region (Cloudflare geo routing).
- 04step
Data never replicates cross-region; backups too stay in-region.
Cases & edge cases
watch for theseMulti-region is a 6-12 month effort done right. Don't promise before delivering.
Some vendors (Resend, Stripe) have region options — verify you can use them.
Cross-region admin queries are a hot mess. Have a 'global view' service that aggregates carefully.
Decisions
pick once, live with itDecision 01
When to commit to EU-only data residency?
pickWhen your first €50K+ ARR customer asks (or for GDPR exposure reduction).
whyBelow that, contractual commitments + SCCs cover most asks. Above it, the engineering investment pays back.
SOC 2 Readiness
SOC 2 Type II is the standard B2B SaaS audit. Type I says 'controls exist'; Type II says 'they worked for 6 months'. Drata or Vanta automates evidence collection (read-only API integrations into Vercel, Postgres, GitHub, etc.).
How it flows
step by step- 01step
Select compliance platform (Drata / Vanta) and plug in vendors.
- 02step
Auto-evidence: MFA enforcement, encryption settings, vendor list, code review enforcement — pulled continuously.
- 03step
Policies generated from templates → tailored → signed by team annually.
- 04step
Audit window (6+ months for Type II) → auditor review → SOC 2 report.
- 05step
Report shared with customers under NDA via your trust center.
Cases & edge cases
watch for thesePick an auditor BEFORE the platform — they want certain platforms integrated.
Engineering effort = 80% in the first 3 months, 20% steady-state.
Trust center (Drata, Vanta, SafeBase) makes 'send me your SOC 2' a self-serve link.
Vendors & tools
what implements thisChecklist
ship readiness- must
Platform selected + integrations live
- must
Policies authored + signed
- must
Auditor engaged 3 months before window
- should
Trust center URL live
Apple Pencil draws with pressure. Fingers still scroll. Saved per pillar.