Skip to content

Automation  ·  Legal and compliance

How to build data retention enforcement

The privacy notice says support tickets are kept for three years. The help desk holds every ticket since 2016, and so does the warehouse copy of it. The model behind a retention schedule that actually deletes, the prompts that build it, and what it takes to do it safely.

Built with Tray Headless

  1. System Retention schedule
  2. Step Find what is past its date
  3. Step Check for holds
  4. Step Delete and read back
  5. System Zendesk
Also Owner approves first runs

Nothing is deleted until the legal hold check has passed, and every deletion is read back and recorded.

The short answer

What is data retention enforcement?

Data retention enforcement has four parts: the retention schedule written as a rule per system and record type, a regular search for records past their date, a check against legal holds and open obligations before anything is deleted, and a record of what was deleted, when and under which rule. The usual failure is the copies. The source system gets cleaned and the warehouse, the export in a shared drive and the marketing tool keep every record, so the schedule is only true in the place nobody else reads.

Stage 6 of 7: Retention and deletion. Part of Compliance automation, end to end : every stage, the systems it runs on and the guide that builds it.

What matters here

  • Write the schedule as rules per system. A policy document nobody can run deletes nothing.
  • Include the copies. The warehouse and the exports hold the same records as the source, for longer.
  • Check for legal holds before every run. A deleted record under a hold is far worse than a record kept too long.
  • Have the owner approve the first runs. Once the counts look right, let it run on its own.
  • Record every deletion by rule and count. Proving you deleted is half the control.

Who this is for

You run privacy, legal or data governance. The retention schedule is written down, nothing enforces it, and the oldest records in most systems are older than the policy allows.

How it works in practice

What happens each run, from the schedule to records actually gone.

  1. 1

    The schedule is written as rules

    For each system and record type: how long it is kept, from which date, and what happens at the end, delete or make anonymous.

  2. 2

    Records past their date are found

    In each system on the schedule, including the warehouse and other copies, counted by rule.

  3. 3

    Holds and obligations are checked

    Legal holds, open disputes, live contracts and financial records with their own retention period are taken out of the run.

  4. 4

    The owner approves while the rule is new

    For the first runs of each rule, the system owner sees the count and a sample, and approves before anything is deleted.

  5. 5

    Records are deleted and read back

    In each system, in batches, with a check afterwards that they are gone and a retry for anything that failed.

  6. 6

    The run is recorded

    Rule, system, count found, count held back with the reason, count deleted and the date.

What retention enforcement is made of

Four parts. The third is the one that makes deleting safe.

A schedule you can run

One rule per system and record type, with the period, the start date it counts from, and the action at the end.

Every copy in scope

The source system, the warehouse, the marketing and analytics tools, and the shared drives where exports end up.

Holds checked first

Legal holds, disputes, live contracts and records with their own required period, checked before every run and never skipped.

A record of what went

Counts by rule, what was held back and why, and the read-back result, kept longer than the records themselves.

The Tray Headless prompts

Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.

Once per project, run /tray-workflows:set-workspace to pick the workspace these build in. Point it at a sandbox first.

  1. 1

    Set up, then write the schedule as rules

    The schedule is the control. The rest is mechanism.

    Headless skills build-workflow

    Use build-workflow. The systems in play are Salesforce, Zendesk,
    Marketo, Snowflake, Google Drive, Box and Slack, or whatever we run in
    those seats. Before you plan anything, tell me which of them are
    already authenticated in the workspace, because I do not want a
    connector stubbed that I have not authenticated.
    
    Then turn our retention schedule into a table: system, record type,
    how long it is kept, the date it counts from (created, closed, last
    activity, contract end), the action at the end (delete or make
    anonymous), and an owner.
    
    Add a row for every copy of each record type: the warehouse tables,
    the marketing database, exports in shared drives. Flag any record type
    that exists in more than one place with no rule for the copy.
  2. 2

    Find what is past its date

    Count first, delete later.

    Headless skills build-workflow tray-gotchas

    Use build-workflow and tray-gotchas. Each month, for every rule, find
    the records past their date in that system. Count them and take a
    sample of ten.
    
    Do not delete anything in this step. Write the counts and samples to
    Snowflake, so the first run is a report of how far behind the
    schedule each system is.
    
    Handle systems that can only be searched in pages, and dates that are
    blank: a record with no close date is never past its date, so report
    it instead of deleting it.
  3. 3

    Check holds before every run

    A deleted record under a legal hold is the worst outcome on this page.

    Before any record is deleted, remove from the run anything that is:
    
      Under a legal hold, from the hold register legal keeps
      Tied to an open dispute, claim or investigation
      Tied to a contract still in force
      A financial or tax record with its own required period
    
    If the hold register cannot be read, stop the whole run and tell
    legal. Never treat a missing hold list as an empty one.
    
    Record every record held back, with the reason.
  4. 4

    Delete with approval while a rule is new

    Deleting is permanent, so earn the right to run it unattended.

    Headless skills build-workflow tray-patterns

    Use build-workflow and tray-patterns. For the first three runs of each
    rule, send the system owner a Slack message with the count, the
    sample and the holds taken out, and buttons to approve or stop.
    Delete only after approval. After three approved runs with no
    problems, let the rule run on its own and send the owner the counts
    afterwards.
    
    Delete in batches. After each batch, read back a sample to confirm
    the records are gone, and retry anything that failed. Where the rule
    says make anonymous, replace the personal fields and keep the record.
    
    Delete the copies in the same run as the source, so the warehouse
    never holds what the source no longer does.
  5. 5

    Record what went

    Proving you deleted is half the control.

    For every run, write to Snowflake: rule, system, records found, held
    back with reasons, deleted, made anonymous, failed, and the date. Keep
    this record longer than any record it describes.
    
    Report monthly: systems behind their schedule, rules with no owner,
    record types with copies not covered by a rule, and runs that stopped
    because the hold register could not be read.
  6. 6

    Check it end to end, then hand the schedule to privacy

    Because the schedule changes and the people who own it should change it.

    Run the per-step checks and the whole-workflow audit before this
    touches production. Test with a record under a legal hold, a record
    with no close date, and a record that exists in both the source and
    the warehouse, and confirm each is handled correctly.
    
    Then open the same workflow in Tray Build so privacy and legal can
    change the rules, the owners and the approval step in the visual
    canvas.

What it connects to

Records live in the business apps, copies live everywhere else, and the hold register decides what stays.

Salesforce

Find closed accounts, old leads and contacts past their date, and delete or make them anonymous.

Reads and writes

Zendesk

Find closed tickets past their period and delete them with their attachments.

Reads and writes

Marketo

Remove people whose records were deleted at the source, so the marketing copy does not outlive it.

Reads and writes

Snowflake

Delete the warehouse copies in the same run, and keep the record of every run.

Reads and writes

Google Drive

Find exports and spreadsheets past their period in the folders the schedule covers.

Reads and writes

Box

Apply the same rules to documents kept in Box.

Reads and writes

Slack

Ask the owner to approve the first runs of each rule, and send counts afterwards.

Writes

Same build, other stacks

The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Dynamics 365, Google BigQuery, Microsoft Teams, Jira, SharePoint or HubSpot.

Connections in this build

Field mapping, templates and common problems for each pairing: Salesforce + Zendesk, Marketo + Salesforce, Snowflake + Marketo and Google Drive + Salesforce.

Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.

Running it in production

This deletes records permanently, across systems. The checks before and after matter more than the deletion itself.

It runs on the platform, not on your laptop

Searches, holds checks, batches and read-backs run on the same engine, with a full history of each run.

No hold list, no run

If the legal hold register cannot be read, the run stops. A missing list is never treated as an empty one.

Credentials are managed, never written into the build

Delete permission across the CRM, help desk and warehouse is about as sensitive as it gets. Each is a separate authentication in your workspace, scoped and separately revocable.

Privacy owns the schedule

Rules, owners and the approval step open in Tray Build, changed by the team accountable for the policy.

It earns the right to run alone

Each rule runs with the owner's approval until three runs have gone cleanly, then runs on its own with the counts reported.

Questions people ask

Why include the warehouse and exports?

Because they hold copies of the same records, usually for longer. Cleaning the source and leaving the copies means the schedule is only true in one place.

What if a record is under a legal hold?

It stays, whatever the schedule says, and the run records that it was held back and why. If the hold register cannot be read, nothing is deleted.

Should deletion run without anyone approving it?

Not at first. The owner approves the first few runs of each rule after seeing the count and a sample. Once those have gone cleanly, the rule runs on its own and the owner gets the counts.

How is this different from a deletion request?

A deletion request is one person asking for their data to go. Retention enforcement applies the schedule to everyone's records on a regular cycle. Both use the same hold checks.

Does this make us compliant?

No workflow does that. It makes the schedule you wrote actually run, and keeps the record. Whether the schedule itself is right is a question for your legal team.

Last reviewed October 2026.