Part 4 · Running It Lawfully

4 · Operate

Running the system: keeping it lawful while it runs. Eight operational obligations dominate engineering time. Each is a pipeline, not a button, each crossing every service boundary, each on a hard deadline (typically one month, extendable to three). The central tension is GDPR's right-to-be-forgotten vs modern architecture's love of immutability, and §4.2 meets it head-on.

4.1Retention & deletion

References

GDPR Art. 5(1)(e), the storage limitation principle. Also Art. 17 (erasure on expiry) and Art. 30 (documenting retention in the RoPA).

The ruleEvery personal-data store gets a documented retention period enforced by native TTLs / lifecycle rules (not crons), plus an attestation job proving it actually fires.

Why we care

"Forever" is not a retention period. Auditors will ask for the runbook and the logs proving enforcement actually happened.

Key patterns

  • Retention catalog. A single source of truth (YAML, Terraform module, or a row in your data catalog) mapping {system, table_or_topic, data_category, retention_period, legal_basis, deletion_mechanism}. The catalog is generated into TTL configs, never hand-maintained alongside them.
  • TTL at the storage layer. Prefer native TTLs over cron jobs. DynamoDB TTL, Redis EXPIRE, MongoDB TTL indexes, Cassandra TTL, Snowflake retention. Cron jobs miss rows; TTLs don't.
  • Lifecycle rules on object storage. S3 Lifecycle. Use prefix-based rules tied to data category. Verify rules actually fire: set up a CloudWatch alert when expected lifecycle transitions stop.
  • Partition-by-date. For warehouses (Snowflake, Redshift) and lakes (Iceberg, Delta), partition by ingest date. Then "delete data older than N days" is a partition drop, not a row-level DELETE: cheaper, faster, and verifiable.
  • Retention proof. Periodically run an attestation job that samples each store and confirms the oldest record is within the configured window. Output a signed report. This is the artifact you hand to auditors.

Anti-patterns / gotchas

  • "We'll delete it when we need the space." Storage limitation is not contingent on disk pressure. The clock is the legal basis duration, not the cost.
  • TTL drift. Engineers extend TTLs in a hotfix and forget to revert. Treat TTL changes like schema changes: PR, review, log.
  • Backups silently retained beyond live retention. Your live system deletes at 30 days but your nightly backup is retained 7 years. The backup is still personal data. Either align backup retention with live retention, or document the rolling restore commitment (see 4.2).
Cloud notes: AWS · K8s
  • AWS: DynamoDB TTL (eventual; AWS now only commits to deletion "typically within a few days" of expiry, so do not rely on it for hard deadlines); S3 Lifecycle (transitions + expiration); RDS automated backups have a max 35-day retention window; Glue/Athena partitioned tables for warehouse retention. CloudTrail and Config track lifecycle rule changes.
  • Kubernetes: Logs, ephemeral volumes, and PVCs need their own retention. Fluent Bit / Vector + sink retention. Don't forget Persistent Volumes that outlive the pod.

4.2Right to erasure

References

GDPR Art. 17, the right to be forgotten. Read with Art. 19 (notifying recipients) and Recital 66.

The ruleHard-delete on request across live stores, caches, indexes, and lakes; for immutable surfaces (backups, event logs, models) use crypto-shredding, tombstones, snapshot expiry, and erasure-on-restore, then document the residual.

Why we care

This is the single hardest engineering obligation in GDPR. It runs counter to almost every modern data-architecture choice we make for scalability, auditability, and ML. You cannot postpone designing for this until the first request arrives.

The honest premise: you cannot perfectly delete personal data from an immutable system. That is the architectural truth. Event logs, append-only lakes, immutable backups, distributed snapshots, content-addressed stores, and trained model weights all resist row-level deletion by design.

GDPR does not require the impossible. It requires that you take reasonable, proportionate steps, that you document the residual risk, and that you have a defensible plan for the bytes you cannot reach today. The accepted pragmatic patterns are:

  1. Crypto-shredding: encrypt per-subject (or per-tenant with a subject sub-key); destroy the key on erasure. The ciphertext is then statistically equivalent to noise. This is a widely accepted approach for data you cannot physically delete (immutable backups especially); no single EDPB guideline endorses it by name, so document the reasoning and treat destroying the key as the erasure event.
  2. Erasure-on-restore covenants: a documented, tested process where any restore from a backup must re-apply the erasure queue before the data goes live. CNIL backup guidance accepts this for backups whose deletion would be disproportionate.
  3. Tombstone propagation: compactable logs (Kafka with cleanup.policy=compact) accept a null-payload tombstone for a key. Compaction physically removes the prior value.
  4. Subject-deletion markers in lakes: Iceberg row-level deletes (MERGE INTO ... WHEN MATCHED THEN DELETE) or Delta DELETE FROM. The file rewrite removes the row from current snapshots; historical snapshots are then expired.
  5. Re-training or unlearning: for models trained on personal data, the realistic options are scheduled re-training without the erased subject's data, or, for a small but growing class of models, machine unlearning techniques.

The rest of this section walks through each surface in production and the pattern that applies.

Key patterns by surface

  • Live transactional stores
    • Hard delete is the default. Postgres, MySQL, DynamoDB: just issue the DELETE. Don't soft-delete and call it done; a deleted_at column is not erasure under Art. 17.
    • Cascade. Foreign-key cascades or explicit child deletes. Do not leave orphan rows that re-identify via join.
    • Replicas. Confirm the delete propagated to read replicas, cross-region replicas, and any logical replication consumers (CDC).
    • Connection pools and prepared statements. Some drivers cache result sets. A stale read after delete is fine; a stale write that resurrects the row is not.
  • Caches
    • Explicit invalidation. Redis, Memcached, application-level caches all invalidate on the same transaction (or via outbox) as the delete. Don't rely on TTL to "eventually" forget.
    • CDN and edge caches. CloudFront, Cloudflare, Akamai: purge by tag or path. Personal data should never have been on a public CDN, but profile photos and similar often are.
  • Search indexes
    • OpenSearch / Elasticsearch. DELETE BY QUERY works for moderate volumes but is heavyweight. For high-volume indexes, route by subject and drop the routed shards, or use index-per-tenant with index deletion.
    • Algolia / Typesense / Meilisearch. Each has a deleteObject API; call it from the erasure handler.
    • Vector stores. pgvector, Pinecone, Weaviate, Qdrant, Milvus. Embeddings of personal text are personal data. Delete by metadata filter; if the store lacks delete-by-filter (some do), maintain an external ID-to-vector-ID map.
  • Immutable event logs
    • Kafka, compacted topics. Set cleanup.policy=compact (or compact,delete) for any topic keyed by subject identifier. Publish a tombstone (key=subjectId, value=null); compaction removes the prior value at the next cycle. Tune min.cleanable.dirty.ratio and segment.ms so compaction actually runs.
    • Kafka, non-compacted streams. If the topic is keyed by something other than subject (e.g., order ID), compaction won't help. Options: (a) re-key the topic via a transform job into a compacted topic and discard the original after retention, (b) shorten the topic retention so the personal data ages out within the legal-basis window, (c) crypto-shred: encrypt the payload per subject and destroy the key.
    • EventBridge / Kinesis replay. Kinesis has a max 365-day retention, and replay-able streams are still personal data. Apply the same patterns: short retention, crypto-shred, or projection-only consumption (downstream projections accept tombstones).
    • Event sourcing in a domain DB. If the aggregate stream is the source of truth, you cannot just delete events without breaking the aggregate. Pattern: snapshot the aggregate with personal fields nulled, then truncate the stream up to the snapshot. Alternatively, encrypt PII fields in the event payload with a per-subject DEK and destroy the DEK on erasure.
  • Append-only data lakes
    • Apache Iceberg. Row-level deletes via merge-on-read or copy-on-write: DELETE FROM table WHERE subject_id = ?. Then expire snapshots older than your delete (CALL system.expire_snapshots); otherwise the row is still readable via time travel. Then run rewrite_data_files to compact away the delete files.
    • Delta Lake. DELETE FROM followed by VACUUM with retention shorter than the default 7 days (you'll need spark.databricks.delta.retentionDurationCheck.enabled=false and a clear sign-off, since the default is there to protect time-travel consumers).
    • Apache Hudi. Record-level delete via the writer API.
    • Plain Parquet on S3. No row-level delete; you must rewrite partitions. Partition by something that lets you target rewrites cheaply (subject hash bucket, ingest date), never by primary key directly (creates millions of tiny partitions).
    • Time-travel features. Iceberg snapshots, Delta time travel, Snowflake Time Travel + Fail-safe. After deletion, expire/drop these windows or document why the residual exposure is acceptable. Snowflake Fail-safe is 7 days and not user-controllable, so flag this in the DPIA.
  • ML training data and models
    • Training corpora. Treat as a regular data store and delete from the lake or feature store as above.
    • Trained model weights. For most production models, the practical answer is re-train on the next scheduled cadence (weekly, monthly) without the erased subject's data, and document the residual window. Where the subject's contribution is non-negligible and identifiable, machine unlearning research is starting to provide options, but most are not yet production-ready. For LLMs trained on web-scale data, the EDPB's emerging position is that controllers must implement reasonable mitigation (output filtering, fine-tuning to suppress) rather than re-train from scratch.
    • Feature stores. Feast, Tecton, SageMaker Feature Store: delete by entity ID, and confirm both online and offline stores delete.
    • Embeddings. Already covered under vector stores. Worth restating: an embedding of personal text is personal data.
  • Backups
    • The tension. Backups are usually immutable, often encrypted, often off-site, often legally required for business continuity. Restoring just to delete one user is grossly disproportionate.
    • Rolling retention. Live data is purged at N days; backups roll out at N + backup-retention. Document this; the regulator accepts it provided backup retention is itself proportionate. CNIL has explicit guidance.
    • Erasure-on-restore covenant. Every restore runbook includes "before exposing restored data to live traffic, apply the pending erasure queue." Test this in DR drills. Without testing it is theatre.
    • Crypto-shredding. Per-tenant or per-subject envelope encryption. Backups encrypted with the subject DEK become unreadable once the DEK is destroyed.
    • WORM and compliance lock. S3 Object Lock in Compliance mode means these objects cannot be deleted even by the root account until the retention expires. Useful for SOX/HIPAA, dangerous for GDPR. Resolve the conflict in the DPIA, usually by ensuring WORM-locked backups are encrypted with a key you control, so crypto-shredding remains an option.
  • Erasure replay queues
    • The queue. A durable record of every accepted erasure request: subject ID, timestamp, scope, status, completion log.
    • Why it exists. (1) Idempotency, so re-runs don't duplicate work. (2) Restore replay: after a backup restore, walk the queue and re-erase. (3) Audit: it proves you did what you said.
    • Retention of the queue itself. It contains subject identifiers, which are personal data. Keep it only as long as needed to prove erasure (typically the limitation period for regulator action, where 3 years is common), then hash or remove the identifiers.

Anti-patterns / gotchas

  • Soft delete only. A deleted_at timestamp is not erasure. Auditors will check.
  • Forgetting the dark corners. Logs (especially application logs), CI artifacts, support tickets, Slack/Teams threads, screenshots in Jira, error trackers (Sentry, Rollbar), analytics (Segment, Amplitude, GA4), CRM exports, BI dashboards with cached datasets. Map them all in the RoPA, and either erase them or document why they are out of scope (e.g., aggregated and irreversibly anonymized).
  • Treating "anonymized" as a get-out. Anonymization must be irreversible; hashed identifiers are pseudonymization and still personal data (see 1.2).
  • No deadline on downstream confirmation. You issued the delete event; did every downstream service acknowledge? Without an SLA per consumer and an alert when one lags, you have no way to prove completion within the 30-day window.
  • Erasure replays missing on restore. The single most common audit finding for mature programs: erasure works in live, but a DR drill restored backups and nobody replayed the queue. The restored data became live again. Test this.
Cloud notes: AWS · K8s
  • AWS: S3 Object Lock (governance vs. compliance mode); KMS key deletion (7 to 30 day waiting period, so plan crypto-shredding around this); DynamoDB on-demand backup retention; AWS Backup vault lock; Glue/Athena over Iceberg for lake-side deletes; OpenSearch Service DELETE BY QUERY. Aurora Backtrack and PITR windows are personal-data exposure surfaces, so set them tight.
  • Kubernetes: Pod logs, node-local logs, container image caches (multi-stage builds occasionally embed test data, so review your Dockerfiles), persistent volumes after pod deletion (reclaim policy Delete vs Retain), Velero backup retention, etcd snapshots if you self-host.

4.3Event-driven deletion propagation

References

GDPR Art. 17 and Art. 19 cover the controller's obligation to communicate erasure to recipients (external processors and other controllers). Internal downstream systems aren't "recipients"; deleting from them is part of your own Art. 17 obligation.

The ruleFan out "delete user X" over a durable bus with at-least-once delivery, idempotent handlers, and a saga that tracks every service's ack within SLA.

Why we care

In a microservices estate, "delete user X" is a fan-out problem. Doing it synchronously across 40 services in a single transaction is impossible. Doing it asynchronously without guarantees is unsafe. You need a propagation pattern with at-least-once delivery, idempotent handlers, and observable completion.

Key patterns

  • Outbox + UserDeletionRequested event. The originating service (usually the identity or accounts service) writes the deletion request to a local outbox table inside the same transaction that marks the user pending-deletion. A relay (Debezium, Kafka Connect, custom poller) publishes the event to a durable bus (Kafka, SNS, EventBridge). This gives you exactly-once production semantics from the source.
  • Per-service handlers. Each downstream service subscribes, performs its local erasure (DB delete, cache invalidation, lake-row tombstone, index removal, blob delete), and emits a UserDeletionCompleted event with its service name and timestamp.
  • Tombstoning vs. hard delete. For compacted Kafka topics keyed by subject, the handler publishes a tombstone (null value) for the subject's key. For regular stores, hard delete. Document per topic which pattern applies.
  • Idempotency. Handlers must tolerate replay. Either (a) check if the subject still exists before deleting and treat absence as success, or (b) maintain a processed-events table keyed by (event_id, service).
  • Saga orchestration for tracking. An orchestrator service (or a deletion_request aggregate) tracks which services have ack'd. When all expected services ack within SLA, the orchestrator marks the request complete and notifies the user. When any service lags past SLA, it pages on-call.
  • Out-of-band processors. External processors (Stripe, SendGrid, Intercom, Segment, Snowflake reverse-ETL destinations) won't subscribe to your Kafka topic. The orchestrator calls their delete APIs and tracks completion the same way.

Anti-patterns / gotchas

  • Synchronous fan-out via HTTP. Brittle, slow, and partial failures leave the system in an inconsistent state with no replay.
  • Fire-and-forget pub/sub. No tracking of which consumers ack'd. You cannot prove completion within 30 days. Always wrap pub/sub in a saga or completion ledger.
  • At-most-once delivery. SNS without DLQs, EventBridge without retry config. Erasure must be at-least-once with idempotent handlers. Verify subscription configs.
  • Forgetting late joiners. A new service onboards next quarter and inherits old data via a backfill. If it didn't process historical deletion events, the backfill resurrects erased subjects. Solution: the new service must subscribe from the start of the topic and replay against the erasure queue (see 4.2).
Cloud notes: AWS · K8s
  • AWS: Kafka (MSK) with compacted topics for subject-keyed streams; SNS + SQS with DLQs for fan-out; EventBridge with archive + replay for cross-account events; Step Functions for saga orchestration with explicit timeouts per state.
  • Kubernetes: Each service is a deployment with its own consumer group offset. Watch for offset resets on pod replacement causing reprocessing; your handlers must be idempotent.

4.4Right of access & portability

References

GDPR Art. 15 (access) and Art. 20 (portability).

The ruleAutomate a DSAR pipeline that verifies identity, fans in from every service, redacts third parties, and delivers machine-readable data securely. The clock starts on receipt, 30 days.

Why we care

Access is a fan-in problem (the inverse of deletion). You must collect, deduplicate, package, and deliver, securely, within one month (extendable to three for complex requests). Most engineering teams discover at the first DSAR that nobody knows where all the data is.

Key patterns

  • DSAR pipeline as a workflow. Standard stages: (1) intake, (2) identity verification, (3) fan-out to per-service collectors, (4) aggregation, (5) review and redaction, (6) packaging, (7) delivery. Each stage is observable; the pipeline has a clock and pages on-call at risk thresholds.
  • Identity verification. Don't disclose data to the wrong person; that is itself a breach. For authenticated users, re-authenticate (step-up MFA). For ex-customers, use out-of-band verification (signed declaration plus a second factor like document upload). Document the verification standard in the runbook; over-verification is also a violation.
  • Per-service collectors. Mirror the deletion fan-out: every service exposes a GET /dsar/{subjectId} internal endpoint that returns its holdings as structured JSON. Owners maintain the endpoint; the catalog (4.1) lists which services must respond.
  • Aggregation and dedup. A coordinator pulls from each service, dedupes by canonical entity ID, and produces a single artifact. Include metadata: source system, retention basis, recipients.
  • Machine-readable export. JSON is the default. CSV per entity type is acceptable for portability under Art. 20. Pure PDF is not portable; it is access-only. Provide both for clarity.
  • Secure delivery. Encrypted archive, signed download URL with short TTL, MFA-gated portal. Email attachment is not appropriate.
  • 30-day deadline (extendable to 90). The clock starts when the request is received, not when verification completes. If you're going to extend, you must inform the subject within the first month and explain why.

Anti-patterns / gotchas

  • Manual collection. "Sarah from data ops will pull it together." This is the single most common cause of late DSARs. Automate the fan-out.
  • Including third-party personal data. A DSAR for user A may pull up messages where user B is mentioned. Redact other people's data before delivery; that is also required under Art. 15(4).
  • Forgetting derived data. Profiles, segments, ML feature values, support agent notes: all in scope. The user has a right to know what you inferred, not just what they gave you.
Cloud notes: AWS · K8s
  • AWS: Step Functions for the workflow; Lambda collectors per service; S3 with KMS-encrypted bucket and presigned URLs for delivery; Cognito for re-authentication.
  • Kubernetes: Argo Workflows or Temporal for the orchestration is common.

4.5Right to rectification

References

GDPR Art. 16. Also Art. 19 (notifying recipients of the rectification).

The ruleCorrect at the source of truth and propagate the fix through CDC, read models, the warehouse, BI caches, and processors, with a version so consumers know which copy is current.

Why we care

A single field update in the source of truth fans out into every downstream copy, and every one of them must be corrected, provably.

Key patterns

  • Source-of-truth-first. Updates land in the authoritative system first. Never let read models or warehouses be the place a correction is made; they will drift back on the next reload.
  • CQRS read-model rebuild. For systems using CQRS, a rectification event triggers a targeted projection rebuild for affected aggregates. Don't rebuild the whole projection (too expensive), but do verify the targeted rebuild covered every read model.
  • Cache invalidation. Same as for deletion: explicit, transactional, observable. A stale cache is an unrectified copy.
  • Warehouse propagation. Most warehouses are loaded via batch or CDC. For CDC, the update flows naturally. For batch, you need either an UPDATE job that runs on the next load, or a partition rebuild. Track the lag: the user expects correction "without undue delay," which is generally read as days, not weeks.
  • Notifying recipients. Under Art. 19, if you shared the data with third parties (processors or other controllers), you must notify them of the rectification, unless impossible or disproportionate. Maintain a recipients list per data category; the rectification handler iterates it.

Anti-patterns / gotchas

  • Patching read models directly. Eventually overwritten by the next projection rebuild: a regression waiting to happen. Always go through the write side.
  • Forgetting BI cached datasets. Looker, Tableau, Power BI all cache extracts. Refresh schedules must be tight enough that rectifications propagate within the legal window.
  • No version on the rectified record. Without a version or updated_at, downstream consumers cannot tell which copy is current. Always increment and propagate the version with the change.
Cloud notes: AWS · K8s
  • AWS: DMS for CDC; Glue jobs for warehouse batch updates; ElastiCache for cache invalidation events; SNS for notifying downstream recipients of the rectification.
  • Kubernetes: Same rules. Make sure your event-driven services use the same Art. 16 propagation pattern as Art. 17.

4.6Right to object

References

GDPR Art. 21. Read with Recital 70 (direct marketing) and Art. 6(1)(e)/(f) (the lawful bases that can be objected to).

The ruleObject is per-purpose suppression, not deletion. Keep an objected_purposes flag and a hashed suppression list that survives erasure; for direct marketing, stop immediately at send time.

Why we care

Object is not erasure, and treating it as erasure is a common bug. The data isn't deleted; processing for the objected purpose stops. The user may still be a customer, still be billed, still log in, they just stop being profiled, marketed to, or scored for that purpose. Engineering this correctly is a per-purpose suppression problem, not a per-subject deletion problem.

Two flavours, very different semantics

Direct marketing (Art. 21(2)-(3)): Absolute right. No balancing test. Must be effective immediately. Applies to any direct marketing (email, push, in-app, SMS, retargeting pixels) regardless of lawful basis. Legitimate interest or public task processing (Art. 21(1)): The user objects; you must stop unless you can demonstrate compelling legitimate grounds that override the user's rights, or the processing is needed for legal claims. The override decision is rare and must be documented.

Key patterns

  • Per-purpose suppression flag, not a delete. On the subject record (or in the consent/preferences service from 3.5), maintain objected_purposes: [marketing, profiling-for-fraud, ...]. Pipelines gate on this attribute; the subject's data stays where it is.
  • Suppression list, not deletion. For marketing, maintain a suppression list keyed by the canonical subject ID and any external identifier the marketing tools key on (email hash, phone hash, ad IDs). If you later re-acquire the user from a new channel, the suppression list prevents re-targeting.
  • Same fan-out pattern as 4.3. An UserObjectedToPurpose event is published; downstream services (ESP, CDP, ad platforms, ML feature stores, reverse-ETL syncs) subscribe and apply the suppression. Tracking, idempotency, and saga rules are identical.
  • Immediate effect for marketing. "Effective at next campaign send" is not immediate. Suppression must be checked at send time, not at audience-build time. Bake it into the send-path, not the segmentation job.
  • Document the override path. If you ever invoke "compelling legitimate grounds" to keep processing despite an Art. 21(1) objection (e.g., ongoing fraud investigation), that decision must be logged with the legal/DPO sign-off and the user must be informed. Don't let engineers decide this alone.

Anti-patterns / gotchas

  • Treating object as erasure. Deletes too much. Breaks the contract, billing, and legal-obligation flows that don't depend on the objected purpose.
  • Honoring opt-out only at the next campaign build. Common in batch-built audiences. The user can be marketed to between objection and the next build, and that window violates Art. 21.
  • Forgetting to propagate to ad platforms. Custom Audiences on Meta, Customer Match on Google Ads, similar on LinkedIn/TikTok: suppression has to reach them too. Otherwise re-targeting continues via vendor-side lists you uploaded.
  • No suppression record after deletion. If the user objects, then later asks for erasure, you delete the subject record but lose the suppression. If they're ever re-acquired via marketing list purchase or signup, you re-target someone who opted out. Keep suppression as a hashed-identifier list that survives erasure.
Cloud notes: AWS · K8s
  • AWS: Same primitives as 4.3: EventBridge for fan-out, Step Functions for the saga, DynamoDB for the suppression list. AWS End User Messaging (SMS/push opt-out lists) and SES respect suppression lists natively; wire your objection handler to update them.
  • Kubernetes: Same as the rest of 4.x: the objection handler is just another consumer of the deletion-propagation bus. Critically, the send-path service (whatever pushes the email/push/SMS) must read the suppression list synchronously, not from a cached audience.

4.7Right to restriction of processing

References

GDPR Art. 18, restriction of processing. Read with Art. 4(3) (definition) and Art. 19 (notify recipients).

The ruleRestriction is "freeze, don't delete": keep the data, stop using it. Flag the subject as restricted and gate every processing path on that flag; only storage and a short allow-list stay permitted.

Why we care

Restriction is the right engineers most often miss, because it sits between object (4.6) and erasure (4.2) and does neither. It is usually a holding state: the user contests accuracy (Art. 16) or objects (Art. 21), and you must freeze processing until it's resolved. Treat it as erasure and you delete too much; ignore it and you keep processing unlawfully.

Key patterns

  • A restricted flag on the subject, checked on every processing path. Like the objected-purposes flag in 4.6, but broader: when set, all processing except storage halts. Pipelines, profiling, enrichment, marketing, and model scoring skip the subject. The data itself stays put.
  • Permitted-while-restricted is a short allow-list (Art. 18(2)). Storage; processing with the subject's consent; establishment/exercise/defence of legal claims; protection of another person's rights; important public interest. Encode that allow-list and default-deny everything else.
  • Wire it as the interim state of another request. On a rectification (4.5) or objection (4.6) that needs adjudication, set restricted, do the work, then clear it. Restriction is rarely requested in isolation.
  • Same fan-out as 4.3. Publish a ProcessingRestricted / RestrictionLifted event; downstream consumers gate on it. Idempotent handlers, saga tracking, per-consumer SLA: identical machinery to deletion propagation.
  • Notify before lifting (Art. 18(3)). You must inform the data subject before you resume processing.

Anti-patterns / gotchas

  • Implementing restriction as a soft-delete or "disable account" that triggers purge jobs. Restriction must preserve the data; that's the whole point. Don't let "set inactive" cascade into deletion.
  • Restricting in the source DB but missing the warehouse, caches, and ML feature stores. A restricted subject whose features still flow into a live model is still being processed. Gate every consumer, not just the OLTP path.
  • Overloading one status enum for restricted / objected / deleted. Three rights, three different rule sets. Model them explicitly and document the semantics, or someone will conflate them.
Cloud notes: AWS · K8s
  • AWS: Reuse the 4.3 primitives: EventBridge for the ProcessingRestricted fan-out, a DynamoDB attribute (or a row in the preferences store from 3.5) for the flag, Step Functions to run the rectification/objection workflow that sets and clears it.
  • K8s: The restriction handler is just another consumer of the rights bus. The critical part: every read-side and pipeline service must consult the flag synchronously before processing, not from a stale cached audience.

4.8Automated decision-making & profiling

References

GDPR Art. 22. Read alongside Recital 71 and Recital 72, and the EU AI Act (Regulation 2024/1689): prohibited practices apply since February 2025, GPAI-model obligations since August 2025, and most high-risk-system obligations from August 2026 (some embedded / Annex I cases to August 2027).

The ruleIf a model alone makes a decision with legal or similarly significant effect, you need a lawful basis plus safeguards: substantive human review, the right to contest, logged inputs, and versioned model lineage.

Why we care

Many production ML and rules-based systems land in scope of Art. 22 without anyone realizing it: credit decisions, fraud screening, dynamic pricing for individuals, hiring shortlist filters, content moderation enforcement, insurance underwriting. The CJEU's Schufa decision (C-634/21) expanded the scope of what counts as an automated decision and who counts as the decision-maker. Engineers building, hosting, or selling such systems are directly affected.

Key patterns

  • Decision register. Maintain an explicit list of automated decisions in your platform: input data, model or rule set, output, human-in-the-loop status, significance assessment. Reviewed by Legal/DPO at least annually.
  • Article 22 gate. For any decision that is (a) solely automated and (b) produces legal or similarly significant effects, you must have one of the lawful bases (necessary for contract, authorized by law, or explicit consent), plus safeguards: human review on request, right to contest, right to express their point of view.
  • Human-in-the-loop is the cheapest path to compliance. A genuine, substantive human review removes the decision from Art. 22 scope entirely. "A human rubber-stamps" is not substantive; the reviewer must have authority and information to override.
  • Logging and explainability. For each decision, log the inputs, model version, and the key features that drove the outcome. Without this, you cannot deliver the meaningful information about the logic required under Art. 15(1)(h).
  • Opt-out and review API. A standard endpoint and operational process for the data subject to (a) request human review, (b) contest the decision, (c) express their view. Tracked, with SLA.
  • Sub-processor decisions. Schufa (C-634/21) established that the entity producing the score can itself be a decision-maker for Art. 22 purposes, even if a downstream entity formally signs the contract. If you sell scores or risk signals, you may be in scope as a controller, not merely a processor.

Anti-patterns / gotchas

  • "It's just a recommendation." If the human downstream always accepts the recommendation, regulators treat it as effectively automated. The human review must be real.
  • Treating Schufa as narrow. The CJEU's reasoning extends well beyond credit scoring, to any score that materially drives a downstream decision about a person.
  • Skipping the AI Act overlay. Many Art. 22 decisions are also "high-risk" under the AI Act (credit, employment, essential services, insurance pricing). The obligations stack: GDPR Art. 22 and AI Act risk-management, logging, human oversight, post-market monitoring.
  • No model lineage. When the user contests a decision made six months ago by a model that has since been retrained twice, you must be able to reconstruct what the then-current model would have done. Without versioned model artifacts and feature snapshots, you cannot.
Cloud notes: AWS · K8s
  • AWS: SageMaker Model Registry for versioning; SageMaker Model Cards for documentation; CloudTrail for inference auditing; Bedrock Guardrails for LLM-based decisioning.
  • Kubernetes: KServe or Seldon for model serving: ensure your serving layer logs request/response/model-version tuples and that those logs feed a retrievable audit store. Without that, Art. 22 requests will be unanswerable.

Closing notes

Three things to internalize before moving on:

  • Erasure is not a feature, it is an operational discipline. It touches every store, every queue, every backup, every model. Section 4.2 is long because the surface is wide. Map your surface in the RoPA; build the propagation in Part 3; operate the queue here in Part 4.
  • The 30-day clock is real. Access, erasure, rectification all run on the same deadline. Without automated fan-out and a tracked workflow per request, you will miss it. Missing it is itself a violation.
  • Immutable architectures are not exempt; they are accommodated. Crypto-shredding, erasure-on-restore covenants, tombstones, snapshot expiry, partition rewrites, and machine re-training are the accepted patterns. Use them, document the residual risk, and review the residuals annually.

At a glance

8  operational obligations

30 days  the response clock (extendable to 90)

Art. 15-22  data-subject rights in operation

The series

Part 4 of 5

Each right is a pipeline, not a button: fan-out, idempotent handlers, tracked completion within the clock.