WordPress 7.1 runs personal data cleanup requests through cron. That closes a gap for stale export and erasure requests, but it also exposes broken cron runners, custom retention assumptions, plugin exporters that never finish, and support processes that rely on old request rows. Deleting rows manually can remove the timeline needed to explain whether a request was confirmed, completed, failed, or abandoned.
Use this for privacy teams, agencies, membership sites, ecommerce stores, and plugins that register personal data exporters or erasers.
Quick answer
Export a redacted inventory of request IDs, type, status, creation time, confirmation time, completion time, email hash, and owning plugin. Record the WordPress timezone and UTC. Inspect the scheduled cleanup hook, the effective WP-Cron or server-cron runner, last and next execution, locks, errors, and missed schedules. Create synthetic export and erasure requests in each state, age them only on staging, and verify which records are cleaned. Preserve a separate minimal audit log that does not retain the personal payload itself.
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| Unconfirmed | Expired synthetic request | Removed by documented rule |
| Confirmed | Work still pending | Retained or escalated |
| Completed | Past retention window | Payload removed, audit kept |
| Cron missed | Runner disabled | Alert before manual cleanup |
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence | Verification |
| Map requests and retention rules | Inventory pending, confirmed, completed, failed, and expired export and erasure requests with UTC timestamps and plugin ownership. | The cleanup event runs on schedule with a recorded result. |
| Repair the cron runner | Inspect the cleanup hook, recurrence, next run, last run, cron lock, alternate runner, loopback path, and relevant errors. | Synthetic requests follow the documented state and age rules. |
| Test every request state | Test core and plugin exporters or erasers with synthetic records that cover confirmation, expiry, failure, retry, and completion. | Plugin exporters, erasers, email, backups, and downstream stores are covered. |
| Separate payload from audit evidence | Compare the legal retention decision with actual database rows, email logs, support records, backups, analytics, and downstream processors. | Retained audit evidence is useful but cannot recreate personal data. |
What to check first
- Inventory pending, confirmed, completed, failed, and expired export and erasure requests with UTC timestamps and plugin ownership.
- Inspect the cleanup hook, recurrence, next run, last run, cron lock, alternate runner, loopback path, and relevant errors.
- Test core and plugin exporters or erasers with synthetic records that cover confirmation, expiry, failure, retry, and completion.
- Compare the legal retention decision with actual database rows, email logs, support records, backups, analytics, and downstream processors.
- Define the minimal audit evidence retained after cleanup and ensure it cannot reconstruct the removed personal data.
Field notes
- Write the expected result before changing anything and keep one repeatable synthetic fixture for the full test window.
- Record exact versions and UTC timestamps because caches, retries, scheduled actions, and deployments can change the evidence between checks.
- Test the public path and the stored server-side result, not only an admin preview, isolated command, or API response.
- Review the result again after the relevant cache, queue, cron, webhook, and observation window has completed.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
wp cron event list --fields=hook,next_run_gmt,recurrence
wp cron event run --due-now
# Use synthetic requests on staging. Do not edit production request dates.
# Reconcile core rows, plugin data, email, backups, and the minimal audit log.
Why this usually happens
- WP-Cron depends on traffic or a replacement server job that may be missing.
- A plugin exporter fails without moving the request to a terminal state.
- Site timezone and UTC are mixed when request age is calculated.
- Backups and support exports retain personal data after the primary row is cleaned.
Decision rule
Do not delete request rows manually until the runner, state transitions, plugin coverage, backups, and legal retention rule are understood. Cleanup must be repeatable and leave only the approved minimal evidence.
Production verification checklist
- The cleanup event runs on schedule with a recorded result.
- Synthetic requests follow the documented state and age rules.
- Plugin exporters, erasers, email, backups, and downstream stores are covered.
- Retained audit evidence is useful but cannot recreate personal data.
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Map requests and retention rules
- Repair the cron runner
- Test every request state
- Separate payload from audit evidence
- Monitor cleanup and plugin failures
Mistakes to avoid
- Changing production before recording exact versions, UTC timestamps, a stable fixture, the expected result, and a tested rollback point.
- Treating one successful screen as proof while logs, stored records, background jobs, caches, emails, APIs, and downstream systems remain unchecked.
- Testing only as an administrator instead of using the role, device, locale, cache state, request path, and failure branch that users actually reach.
- Leaving debug output, temporary exclusions, helper accounts, duplicate hooks, broad permissions, or relaxed firewall rules active after verification.
Questions teams ask during testing
Can I test this directly in production?
Start with read-only evidence. Use staging for code, package, security, checkout, form, privacy, or cache changes. If a production canary is necessary, make it identifiable, reversible, monitored, and incapable of exposing personal data or charging a customer.
How do I avoid a false positive?
Repeat the same fixture with the same versions, URL, role, locale, cache state, and downstream integration. Compare the public result, stored result, and logs instead of relying on one browser view.
What evidence should I retain?
Keep UTC time, exact versions, request or record ID, expected result, actual result, relevant log lines, change made, rollback point, owner, and final verification. Redact credentials, tokens, and personal data.
When is the work complete?
Close it when the primary path passes, failure branches are understood, stored and downstream records reconcile, temporary changes are removed, monitoring is active, and the owner has the evidence packet.
What to tell the client or owner
Give the owner a concise packet with the affected workflow, exact versions, UTC test time, synthetic fixture ID, expected result, actual result, key logs, change made, rollback point, final result, unresolved risks, owner, and next review date. Remove credentials and personal data before sharing it.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, have HandL WP audit WordPress privacy cleanup.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Helpful references