On this page
- Start with a data inventory
- Conversation deletion should include dependent records
- File deletion needs filesystem cleanup
- Indexes are copies too
- Temporary files should have a lifecycle
- Credentials live outside normal app data
- Provider-side resources may survive local deletion
- Remote deletion can fail
- Background jobs need cancellation
- Tool execution records can contain sensitive data
- Analytics deletion is a separate system
- Backups can preserve deleted data
- Soft delete vs hard delete
- Tombstones should be minimal
- Caches can resurrect data
- Search indexes need deletion tests
- “Delete all data” should be one audited operation
- Avoid broad filesystem deletion without ownership checks
- Restores must respect deleted state
- Multi-device sync complicates deletion
- Provider connection deletion is not the same as account deletion
- Verify deletion after relaunch
- Make deletion idempotent
- Keep a deletion checklist per data type
- Where BYOKchat fits
- Further reading
“Delete conversation” sounds simple until an AI app stores the same logical data in several places.
A single chat may touch:
- the main local database;
- attachment files;
- extracted text;
- full-text or semantic indexes;
- temporary files;
- tool results;
- provider-side uploaded files;
- background jobs;
- analytics identifiers;
- backup archives.
Deleting only one row does not necessarily delete the data.
The right model is:
Define every storage location and lifecycle that can contain the user’s data, then make deletion a coordinated operation across those boundaries.
Start with a data inventory
List each category explicitly.
For a local-first AI client:
conversations
messages
reasoning artifacts
attachments
project files
library files
retrieval indexes
provider connections
API credentials
MCP server configs
MCP credentials
tool execution records
analytics records
cached model metadata
backups / exports
temporary files
Then classify ownership:
app-owned local
platform secret store
provider-side remote
user-exported external
third-party telemetry
Deletion semantics differ by category.
Conversation deletion should include dependent records
A conversation may own:
messages
message branches
attachments
tool rounds
drafts
reasoning summaries
usage metrics
A robust schema either cascades safely or the application performs an explicit deletion plan.
Do not leave orphaned attachment records after the visible chat disappears.
File deletion needs filesystem cleanup
Removing a database reference does not delete the file itself.
If an attachment is stored at:
Application Support/Attachments/<uuid>.pdf
then conversation deletion may need to remove that file when no other record references it.
If files are deduplicated/shared, use reference counting or ownership metadata instead of blindly deleting shared content.
Indexes are copies too
Search and retrieval features may create derived data:
- full-text index entries;
- embeddings;
- chunk records;
- summaries;
- metadata caches.
When the source is deleted, derived representations should be removed too.
Otherwise a supposedly deleted document may remain searchable.
For RAG systems, model the relationship:
source file -> chunks -> embeddings -> index entries
and delete the whole chain.
Temporary files should have a lifecycle
AI workflows often create temporary artifacts:
image resize output
PDF extracted text
audio waveform cache
upload staging file
archive extraction directory
Temporary does not mean self-deleting.
Use deterministic cleanup after:
- success;
- cancellation;
- failure;
- app relaunch after crash.
A startup cleanup pass can remove stale temp files older than a safe threshold.
Credentials live outside normal app data
On Apple platforms, API keys may live in Keychain.
Deleting:
SQLite
UserDefaults
Application Support
will not automatically mean every credential is gone.
Connection deletion should remove the associated secret item.
“Delete all app data” should enumerate and delete all app-owned Keychain entries too.
See How Mobile Apps Should Store AI API Keys.
Provider-side resources may survive local deletion
Some providers support uploaded files, background responses, vector stores, or other server-side resources.
If the app created a remote resource on the user’s behalf, decide whether local deletion should also request remote deletion.
Possible policy:
Delete local only
Delete local + provider resources
The UI should be clear about what each action means.
Do not claim complete deletion if provider-side resources intentionally remain.
Remote deletion can fail
Suppose local conversation deletion succeeds but provider cleanup fails because the device is offline.
You need a policy.
Options include:
queue remote cleanup for retry
show pending deletion state
retain minimal tombstone with remote resource ID
allow user to retry manually
The tombstone should contain only what is needed to finish cleanup, not the deleted conversation content.
Background jobs need cancellation
A deletion can race with active generation.
Example:
1. user deletes conversation
2. background request finishes
3. completion handler re-inserts message
Prevent this by binding background work to a durable operation/conversation identity and checking deletion state before persistence.
A safe sequence:
mark deleting
cancel active work
prevent new writes
remove dependent data
commit deletion
Tool execution records can contain sensitive data
Tool rounds may store:
- arguments;
- results;
- approval state;
- external IDs.
If tool records belong to a conversation, deletion should remove them according to product policy.
If you retain security audit events, strip user content and document the retention reason.
Analytics deletion is a separate system
If analytics uses random local identifiers, resetting/deleting local data should rotate or delete those identifiers when appropriate.
If your server retains product telemetry, be precise about whether it is:
- anonymous/aggregate;
- pseudonymous;
- linked to an account.
Do not conflate local conversation deletion with server analytics deletion unless they actually share identity.
Privacy-preserving analytics reduces this problem by avoiding conversation content in the first place.
See Privacy-Preserving Analytics for AI Apps.
Backups can preserve deleted data
If the user exported:
byokchat-backup-2026-09-01.zip
and then deletes a conversation from the app, the old external archive may still contain it.
The app cannot silently erase copies the user controls elsewhere.
Be explicit:
Deletion removes app-managed copies.
Previously exported backups remain wherever the user saved them.
For app-managed cloud backups/sync, define deletion propagation separately.
Soft delete vs hard delete
Soft delete:
deleted_at = timestamp
can support undo/sync, but the data still exists.
Hard delete removes the content.
If you offer a trash/recently-deleted feature, communicate the retention window.
A local-first privacy claim should not describe soft-deleted content as already erased.
Tombstones should be minimal
Sync and remote cleanup sometimes require a tombstone such as:
{
"object_id": "uuid",
"deleted_at": "..."
}
Do not retain:
message content
attachment content
API credentials
tool results
inside a deletion marker.
Caches can resurrect data
Consider:
memory cache
render cache
thumbnail cache
search result cache
recent-conversation list
After deletion, invalidate cached objects immediately so the user does not see deleted content after navigating back.
Also prevent cached objects from being written back into persistent storage later.
Search indexes need deletion tests
A useful test:
1. create conversation containing UNIQUE_DELETE_SENTINEL
2. index it
3. delete conversation
4. search for UNIQUE_DELETE_SENTINEL
5. expect zero results
Repeat for:
attachment extracted text
project files
library files
tool results
“Delete all data” should be one audited operation
A complete reset might cover:
cancel requests
cancel background jobs
close database handles
wipe database
remove app files
remove attachments
remove indexes
clear caches
clear UserDefaults
remove Keychain credentials
remove OAuth tokens
clear MCP credentials
rotate analytics identifiers
clear local diagnostics
The exact list depends on the app.
Keep it centralized so new subsystems must register cleanup rather than being forgotten.
Avoid broad filesystem deletion without ownership checks
Only delete app-owned paths.
Do not accept a model-generated or restored path and recursively delete it without validating that it lies inside the app’s managed storage boundary.
Deletion code is high-impact code.
Use canonical app-owned identifiers instead of arbitrary paths whenever possible.
Restores must respect deleted state
A user may restore an old backup that contains previously deleted conversations.
That can be a legitimate explicit action.
The app should not accidentally restore hidden data during an unrelated settings import.
Make restore scope clear:
Conversations
Projects
Files
Provider configuration
and separate credentials from backups.
Multi-device sync complicates deletion
If the app eventually supports sync, deletion becomes distributed.
You need rules for:
device A deletes
device B is offline
device B edits old object
device B reconnects
A tombstone/version policy prevents resurrection.
Do not build sync by treating missing records as ambiguous.
Provider connection deletion is not the same as account deletion
Deleting a connection from the app should remove:
local provider config
local credential
cached model metadata tied to connection
It does not delete the user’s provider account.
The UI should avoid ambiguous labels such as:
Delete account
when the action only removes local configuration.
Verify deletion after relaunch
Many cleanup bugs are hidden by memory state.
Test:
delete -> terminate app -> relaunch -> search storage
Also test crash/relaunch during deletion if the operation spans multiple stores.
Make deletion idempotent
Calling delete twice should be safe.
For example:
remove file if exists
remove keychain item if exists
delete DB records if present
cancel remote cleanup if already complete
Idempotency simplifies recovery from partial failures.
Keep a deletion checklist per data type
For every new feature, answer:
Where is the primary data?
What derived copies exist?
What credentials exist?
What remote resources exist?
What cache/index entries exist?
What does backup contain?
How is deletion tested?
This makes privacy part of architecture rather than cleanup work before release.
Where BYOKchat fits
A local-first AI client can offer strong deletion semantics because most user content is under the app’s direct control.
That advantage depends on covering all app-managed copies: conversations, attachments, projects, library data, tool rounds, indexes, caches, credentials, and backups generated by the app.
Provider-side resources and user-exported archives should be handled explicitly rather than hidden behind a vague “deleted” message.