Privacy by Design for Engineers

SecurityPrivacyEngineeringCompliance
Share on LinkedIn

Legal asked for GDPR compliance six weeks before launch. Engineering had already logged full IP addresses, device fingerprints, and page titles in a single analytics_events JSON blob with no TTL. Privacy by design would have asked before the schema shipped: what do we need, for how long, who accesses it, and how do we delete it when users ask?

Privacy by design (Ann Cavoukian's framework) isn't legal paperwork — it's architectural decisions engineers make daily.

Seven principles translated for builders

  1. Proactive not reactive — threat model privacy in design docs
  2. Privacy as default — opt-in for sharing, not opt-out
  3. Full functionality — privacy without breaking core UX
  4. End-to-end security — encrypt in transit and at rest
  5. Visibility and transparency — users know what's collected
  6. Respect for user privacy — deletion actually works
  7. Accountability — audit logs, DPA records

Data minimization at the schema layer

-- BAD: collect everything
CREATE TABLE users (
  email TEXT,
  full_name TEXT,
  ip_address INET,
  device_fingerprint TEXT,
  browsing_history JSONB
);

-- BETTER: purpose-limited
CREATE TABLE users (
  id UUID PRIMARY KEY,
  email TEXT NOT NULL,
  display_name TEXT,
  created_at TIMESTAMPTZ DEFAULT now()
);
-- Analytics: separate table, pseudonymous user_id, 90-day TTL

Challenge every field: What decision does this enable? What breaks without it?

Remove:

Purpose limitation and retention

Tag tables with retention policy in code or metadata:

# data_retention.py
RETENTION_POLICIES = {
    "analytics_events": timedelta(days=90),
    "audit_logs": timedelta(days=2555),  # 7 years regulatory
    "session_tokens": timedelta(days=30),
}

Scheduled job deletes or archives — not manual quarterly scripts someone forgets.

DELETE FROM analytics_events
WHERE created_at < now() - interval '90 days';
-- Batch in chunks to avoid lock storms

Document purposes in privacy policy mapping to tables — legal maintains mapping; engineering implements TTL jobs.

Pseudonymization patterns

def pseudonymize(user_id: str) -> str:
    return hmac.new(PSEUDO_KEY, user_id.encode(), "sha256").hexdigest()[:16]

Store pseudonym in analytics; map key in separate vault with stricter access. Re-identification requires vault access — logged and rare.

Separate analytics database from PII database — analyst queries never join email without approval workflow.

Access control and audit

# Generate fake data for staging
pg_dump prod --schema-only | psql staging
python scripts/seed_synthetic_users.py

Prod data in staging is a privacy incident waiting for a laptop theft.

User rights: export and deletion

Engineering must implement:

Export (DSAR): aggregate user data across services — start with internal user ID index.

def export_user_data(user_id: str) -> dict:
    return {
        "profile": profile_repo.get(user_id),
        "orders": orders_repo.list_for_user(user_id),
        "support_tickets": tickets_repo.list_for_user(user_id),
    }

Deletion: cascade or anonymize — hard delete vs soft delete policy per regulation.

def delete_user(user_id: str):
    orders.anonymize_user(user_id)  # legal hold may block
    profile.hard_delete(user_id)
    cache.invalidate(user_id)
    search_index.remove(user_id)
    enqueue_third_party_deletion(user_id)  # Stripe, SendGrid, etc.

Deletion must reach backups on defined schedule — document backup retention vs erasure requests.

Privacy review in design process

Checklist for RFCs touching user data:

15-minute privacy pass in design review beats quarter-end scramble.

DPIA triggers

Trigger Data Protection Impact Assessment when launching features that process new categories of personal data, large-scale profiling, or systematic monitoring. Engineering RFC checkbox: "DPIA required?" routes to legal early — not two weeks before launch.

Operational notes

Contract third-party SDKs with same retention limits as first-party data — analytics SDK buffering events locally may violate deletion requests if vendor buffer TTL exceeds your policy.

Log data access to PII tables with purpose code — supports GDPR accountability principle and speeds breach impact assessment when logs show who touched affected records.

Review vendor DPAs when adding analytics SDKs — subprocessors list must match actual network calls from mobile builds verified in Charles or mitmproxy during QA.

Privacy engineering checklist

Privacy is not legal-only — engineers implement retention cron and deletion cascades.

Common production mistakes

Teams get by design engineering wrong in predictable ways:

Production implementations of by design engineering fail when staging mirrors production topology poorly, rollback is untested, and on-call runbooks describe the happy path only.

Debugging and triage workflow

When by design engineering misbehaves in production, work top-down instead of guessing:

  1. Confirm scope — one tenant, region, or deployment stage? Narrow blast radius before deep diving.
  2. Check recent changes — deploys, flag flips, config pushes, and schema migrations in the last 24 hours.
  3. Compare golden signals — latency, error rate, saturation, and traffic for the affected surface vs. baseline.
  4. Reproduce minimally — smallest input or scenario that triggers the failure; capture traces/logs with correlation IDs.
  5. Fix forward or rollback — if rollback is faster than root-cause during incident, rollback first, postmortem second.
  6. Add a guard — alert, integration test, or circuit breaker so the same class of failure is caught earlier next time.

Document the timeline during triage. Future you (and on-call) will need timestamps, not just conclusions.

Resources

Frequently asked questions

What is privacy by design for software engineers?

Building privacy into architecture from the start — collecting only necessary data, limiting access, defining retention, enabling deletion, and encrypting sensitive fields — rather than bolting compliance on after launch. Proactive, not reactive.

What is the difference between anonymization and pseudonymization?

Pseudonymization replaces identifiers with reversible tokens keyed separately — still personal data under GDPR if re-identification is possible. Anonymization removes re-identification risk irreversibly. Engineering usually implements pseudonymization first; true anonymization is harder to prove.

Do engineers need legal approval for every data field collected?

Engineers should document purpose per field and challenge unnecessary collection in design review. Legal/privacy teams define requirements; engineers implement technical controls. Collaboration at schema design time prevents 'collect everything' defaults.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →