Here is a bug that is sitting in a large share of AI features shipped since 2024.
A user exercises their deletion right. Your handler runs. It deletes the user row, cascades to their documents, tombstones their events, and returns 204. Everything looks correct.
Meanwhile the chunks of those documents are still sitting in your vector index, embedded and retrievable, and a semantic query will happily surface their content to the next person who asks a related question.
Under Singapore's PDPA — and equally under GDPR, Law 25, or any comparable regime — that index holds personal data. It is subject to the same retention, access control and deletion obligations as your primary store. Very few teams built it that way, because when they added the retrieval feature they were thinking about relevance, not about erasure.
Why the gap happens
Deletion pipelines are usually built once, early, against the relational schema, and then never revisited as the data architecture grows sideways. By year two a typical system has personal data in:
- The primary database (handled)
- Object storage for uploads (usually handled)
- A search index — Elasticsearch, OpenSearch, Typesense (sometimes handled)
- An analytics warehouse (rarely handled)
- A vector store for retrieval (almost never handled)
- Application logs and traces (essentially never handled)
- Backups of all of the above (handled by policy, not by code)
Each of those was added by a different team at a different time to solve a different problem, and none of the additions triggered a review of the deletion path. The vector store is the worst offender because it is the newest, and because its contents are opaque — you cannot eyeball a float array and recognise someone's medical history in it.
The design that fixes it
The core move is to stop treating deletion as a procedure and start treating it as a property of the data model. Concretely: every derived store must be able to answer "which of my records derive from subject X?" without a full scan.
1. Carry the subject identifier into every derived record.
When you chunk and embed a document, the metadata on each vector must include the subject identifiers the source document relates to — not just the document ID, but the user or customer the document is about. These are frequently different. A support transcript belongs to one account but may reference three individuals.
{
"id": "chunk_8f2a",
"vector": [...],
"metadata": {
"doc_id": "doc_1193",
"subject_ids": ["usr_4421", "usr_9087"],
"purpose": "support_retrieval",
"ingested_at": "2026-03-11T04:22:00Z",
"retention_class": "customer_support_24m"
}
}
The subject_ids array is the part that makes deletion possible. The purpose and retention_class fields are what make consent withdrawal and retention enforcement possible, which are separate obligations people conflate with deletion.
2. Make deletion a fan-out over a registry, not a hand-written function.
Do not write deleteUser() as a sequence of calls. That function will be correct on the day it is written and wrong six months later, because the person who adds the next derived store will not find it.
Instead, maintain a registry of erasure handlers, and require registration as part of the definition-of-done for any component that persists derived data:
registry.register('vector_index', {
eraseSubject: async (subjectId) => {
return vectorClient.deleteByFilter({
subject_ids: { contains: subjectId }
})
},
countForSubject: async (subjectId) => { ... }
})
Then your deletion job iterates the registry, and — critically — a test asserts that the registry covers every store listed in your data inventory. When someone adds a new derived store without a handler, CI fails. That is the only mechanism I have seen actually hold over multiple years.
3. Verify, do not assume.
Every erasure run should produce an artefact: which stores were touched, how many records each removed, and a post-check confirming zero remaining for that subject. Store that artefact. When a regulator asks you to demonstrate that your accountability obligations are met, this is the evidence, and generating it retroactively is not possible.
The hard cases
Backups. You cannot surgically delete from an immutable backup, and you should not try. The accepted position is a documented retention window on backups plus a suppression list that is replayed on any restore. Write the suppression replay as actual code and test it, because a restore is exactly the moment nobody is thinking about erasure.
Model fine-tuning. If personal data went into a fine-tuning set, deletion is genuinely hard — the information is diffused through weights. The practical answer is not to fine-tune on personal data at all. Use retrieval instead, where deletion is tractable. If you already have, your options are retraining from a filtered corpus or documenting the limitation honestly in your privacy position.
Cached completions. Prompt and response caches keyed on content will hold personal data. They need a TTL short enough to sit inside your erasure SLA, or they need the same subject tagging as everything else.
Logs and traces. Observability tooling captures request payloads by default. Either redact at the emission point — not at the collector, which is too late — or apply the retention class to your log store and accept a bounded window.
What this costs
Retrofitting subject identifiers onto an existing vector index means a re-ingestion pass. For a corpus of any size that is a day of engineering and some inference spend, and it is the cheapest it will ever be, because the corpus only grows.
Building it correctly at ingestion time costs approximately nothing — it is metadata you already have in scope when you chunk the document. The only reason it is not there is that nobody thought about it at the time.
This is the general shape of compliance engineering: nearly free in sprint one, a quarter of engineering time in month fourteen. The full treatment — PDPA architecture, MAS TRM expectations, and what regulated builds actually cost in this market — is in our guide to application development in Singapore.
We build this kind of thing as a matter of routine in our LLM integration work.
More from TechCirkle
- Software development company in Singapore
- Custom application development company
- Custom software development services
- Mobile app development services
- SaaS development services
- AI development services
- Hire dedicated developers
Frequently Asked Questions
Does a vector embedding count as personal data?
If it can be linked to an identifiable individual — which it can, via its metadata, and often via inversion of the embedding itself — then yes, under PDPA, GDPR and comparable regimes. Treating embeddings as anonymous because they are numeric is not a defensible position.
How do I delete from a vector store that has no metadata filtering?
Some managed vector databases only support deletion by ID. In that case you must maintain an external mapping from subject ID to chunk IDs, which means writing that mapping at ingestion time. If you did not, you need a re-ingestion pass to build it. This constraint is worth checking before selecting a vector database.
Do I need to delete from backups?
Not surgically, and no regulator expects you to. The accepted approach is a documented and bounded backup retention window combined with a suppression list applied on restore. The suppression replay must be implemented and tested, not merely stated in a policy document.
What about data used to fine-tune a model?
Deletion from model weights is not practically achievable. The correct answer is to avoid fine-tuning on personal data, using retrieval instead, where erasure is tractable. If you have already fine-tuned, your options are retraining from a filtered corpus or documenting the limitation explicitly.
How do I stop this regressing as the system grows?
Maintain an erasure handler registry and add a CI test that asserts every store in your data inventory has a registered handler. Hand-written deletion functions drift within months; a failing build does not.
What evidence should an erasure run produce?
A per-run artefact recording which stores were processed, how many records each removed, and a post-check confirming zero remaining records for the subject. Retain these. Under PDPA's accountability obligation you must be able to demonstrate that policy is followed, not merely that it exists.
Does this apply to search indexes too?
Yes, and search indexes are easier to get right because their documents are human-readable and usually already carry identifiers. The same subject tagging and registry approach covers them. The reason they are more often handled is simply that people can see the problem.


Top comments (0)