Personal data

Erase personal data

Erase personal data for tenant admins and governance reviewers.

For: tenant admins and governance reviewers.

Erase

Erasure destroys the keys of eligible jobs and makes their encrypted payloads unreadable. A keep-for period defers eligible jobs, and a legal hold stops erasures. Read what erasure does not reach before applying it.

Terminal
oz0 subject erase [email protected] --reason "GDPR request 2026-114"
oz0 subject erasures

An erasure:

  1. Destroys the keys of the person's jobs, at once, except for jobs a keep-for period keeps. Every payload of those jobs, in Temporal's history, in External Storage and in any backup of either, can no longer be read: it shows as "[erased]". The person's own keys go too.
  2. Redacts the audit entries about the person, looking them up included: their actor, target, detail and private part are blanked, their hashes stay, so the audit chain still verifies. The subject.erase entry lists which entries it redacted. An entry about the person that reaches the log later (a step of a job that was still running) is redacted as it is written, and a subject.redact entry says so.
  3. Deletes the person's jobs from Temporal, child jobs included, with the stored payloads their histories refer to (in the database, a separate payload database or an object store, wherever the edge keeps them; a job started while erasure was off leaves its stored payloads to the 90-day collection, since another job may share them), their job summaries, boards, a routine fire's outputs, kept eval cases, and the files their tools stored or a person handed them (a file another job also holds stays for that job).

Files stored through a node on a runtime from before scoped files, or by an operator without naming a job, belong to no job and are not deleted by the erasure: they go with the 90-day payload collection (see upgrades).

An edge does this within seconds and waits until Temporal has really deleted each run, so subject erasures shows done only when the histories are gone.

A rollout's shadow run that replayed one of the person's jobs is one of their jobs too, and an erased person's jobs are never replayed.

The erasure is in the audit log as subject.erase and subject.erase.done, with the person's hash, who asked and why. subject.erase.done is written in the transaction that marks the erasure done, so an erasure is never done without it: when it cannot be written, the erasure stays pending and the next pass writes it. A legal hold on the tenant stops erasures until it is released, whatever the policy.

Progress when a job cannot be deleted

One job does not hold the others back. A job Temporal cannot delete right now keeps its erasure pending for the next pass, and the erasure's other jobs go on: their runs and summaries are deleted in the same pass.

A deferred job that fails stays deferred, and the jobs beside it are erased.

Each tenant's work is read in lists of its own, up to 100 erasures and 100 due jobs per pass, which move on and come round again, so neither another tenant's erasures and jobs nor a tenant's own failing ones keep it from what comes after them.

A tenant's deletions from Temporal take at most ten minutes of a pass, its erasures and deferred jobs together, and when deferred jobs are due half of that time is theirs: when its Temporal hangs, the other tenants wait that long at most, however much it has pending.

The next pass goes on behind the last erasure or job reached, so work that fails slowly takes its turn and no more; what waits behind it is reached in a later pass, and an erasure is done only when a pass has been through all its jobs.

Older job IDs

Job IDs from before IDs were checked. Starts now refuse an ID with a control character, a backslash or a double quote, and such an ID may be stored from before: Temporal's visibility cannot be asked about it by name.

The eraser reads the IDs that start the same way, as far as a query can write them, and keeps the job's own runs and child jobs, so such a job is erased like any other.

It says so: the subject.erase.done entry and the erasure's report carry jobs_unnameable, and a deferred job's pass writes subject.erase.unnameable, with jobs_partly_found for the jobs it cannot say it found every run of.

That happens when the ID starts with such a character, when more than 10,000 other runs start the same way, or when Temporal refuses the ID: earlier runs and child jobs may then stay until Temporal's retention removes them.

Their keys are destroyed all the same, so what stays cannot be read.

Temporal not answering is none of these: the erasure stays pending and the next pass asks again.

A person's export reads such a job the same way, and its manifest says so when it could not list all of the job's children.

Holds added after acceptance

A hold added after acceptance can delay physical completion. A later legal hold, including one restored from an older backup, blocks final cleanup of retained-history archives and job summaries while it lasts. The erasure stays pending, reads of its erased jobs stay denied and destroyed keys stay destroyed. The hold does not undo completed erasure steps; releasing it lets the pending cleanup continue.

A new job for the same person after an erasure gets new keys, under a new job ID. A job that starts while the erasure runs is either listed in the erasure and erased with the rest, or gets the new keys as a job started after it: never a key the erasure closed or destroyed. A conversation about an erased person does not go on, even from a turn that a keep-for period keeps.

The erasure policy

Who may erase, and whether anyone may, is a tenant setting:

Policysubject erase
allowed (the default)Erases at once, as above.
second-personFiles the erasure as a change request; another admin approves it, and then it runs. The admin who asked never approves it, whatever the tenant's other rules.
offRefused, with a message that says since when, by whom and why.
Terminal
oz0 tenant erasure-policy acme
oz0 tenant erasure-policy acme second-person --reason "the DPO reviews each erasure"

Under second-person:

Terminal
oz0 subject erase [email protected] --reason "GDPR request 2026-114"   # ann asks
oz0 change approve cr-0192abcd --tenant acme --delta sha256:...        # bob approves

The change request holds the person's hash, never the person, with the number of their jobs, who asked and why. subject find shows that it waits. Every step is audited: subject.erase.requested, subject.erase.approved (or rejected), the erasure itself, and subject.erase.applied.

Under off, jobs that name people keep their hashes, so subject find and exports still find them, but they get no key of their own: the tenant's payload key alone seals them. They cannot be erased by key, and turning the policy back to allowed does not change that. A later erasure deletes their rows (histories, summaries, boards) as it deletes any job's, but copies of them in backups stay readable to whoever holds the tenant's key. Whether and when a tenant may turn erasure off is a legal question, not one the platform answers.

The policy is a governance setting: every change takes a reason (tenant.erasure_policy in the audit log), and every change except allowed to second-person loosens, so it waits for another admin where the tenant has four eyes on. A change applies to jobs started after it (on an edge apart from management, within five seconds). In the console it is under Govern › Privacy › Erasure.

What it does not reach

  • Jobs started without a data subject are not encrypted per person. Their history is kept for the tenant's Temporal retention and their summaries for the tenant's retention.
  • Jobs started while the erasure policy was off: above.
  • What tools sent elsewhere: an email a tool sent, a ticket it wrote, a model provider's own logs. Those are the other system's to erase.
  • Copies of a kept eval case outside the workspace. A case kept from the person's job stays in the workspace, where the erasure removes it from every draft and revision; a copy someone downloaded or pasted elsewhere is theirs to delete.
  • Usage rows: what the jobs' model calls used and cost stays, for billing, until the tenant's retention of usage rows deletes it. The jobs' tags, which the usage export copied onto those rows, are emptied with the erasure.

Finding jobs with older invalid IDs

For an older job ID that visibility cannot query by name, other name-only lookups can return no result, including approvals and colleague lookup within the job tree. Erasure and exports use the broader search described under Older job IDs, with jobs_partly_found when coverage is incomplete.

A retained-history copy skips an ID containing a line break, carriage return or NUL, even under a hold or keep-for period. Check the report before relying on a complete export or retained archive.

Copyright © 2026