Ask a WordPress site owner how long their database retains personal data and you will almost certainly get a blank stare. That blank stare mirrors the blank fields in WooCommerce’s data retention settings — five configurable inputs, all shipping empty, all defaulting to forever. It mirrors the unlimited post revisions accumulating in wp_posts, the expired transients rotting in wp_options, the spam comments sitting in wp_comments with full IP addresses and user agent strings from three years ago. WordPress was designed to persist content. Privacy law was designed to limit persistence. These two design philosophies are in direct conflict, and regulators have stopped being patient about it.
Deutsche Wohnen SE discovered this in October 2019, when Berlin’s data protection authority imposed a €14.5 million fine — at the time, Germany’s largest — because the company’s archive system physically could not delete data that was no longer needed. Not a breach. Not a hack. The system simply lacked the ability to forget. That is exactly the architecture WordPress ships with by default.
Storage limitation is not data minimization with a clock
There is a persistent confusion in the WordPress community between data minimization and storage limitation. They are related but distinct obligations, and the distinction matters because you can satisfy one while violating the other.
Data minimization under GDPR Article 5(1)(c) governs the scope of collection — what data is adequate, relevant, and necessary. Storage limitation under Article 5(1)(e) governs the temporal dimension — how long identifiable data may persist after collection. A WooCommerce store that collects only name, email, and shipping address has satisfied data minimization. That same store retaining those fields for a decade after the last order, with no retention policy and no automated deletion, is violating storage limitation. Both violations carry identical maximum penalties under Article 83(5)(a): €20 million or 4% of global annual turnover.
The statutory language of Article 5(1)(e) is precise: personal data must be kept in a form permitting identification of data subjects “for no longer than is necessary for the purposes for which the personal data are processed.” Recital 39 sharpens this to a “strict minimum” and mandates that “time limits should be established by the controller for erasure or for a periodic review.” The EDPB’s Guidelines 4/2019 on Data Protection by Design (paragraph 53) are unambiguous: “If personal data is no longer necessary for the purpose of the processing, then it shall by default be deleted or anonymized.”
The ICO’s guidance translates this into operational language: controllers must have a policy setting standard retention periods, periodically review data they hold, and erase or anonymise it when they no longer need it. The ICO explicitly warns against keeping data indefinitely “just in case.”
No major privacy framework prescribes specific retention periods for specific data categories. The burden falls entirely on the controller. You must determine, document, justify, and technically enforce appropriate periods for every category of personal data you hold. WordPress does none of this for you.
The California shift and the US state patchwork
The CPRA fundamentally changed the US landscape when it became effective January 1, 2023. Section 1798.100(c) requires that a business’s collection, use, retention, and sharing of personal information be “reasonably necessary and proportionate” to the purposes for which it was collected. Section 1798.100(a)(3) adds something no US law had previously required: businesses must inform consumers of the length of time they intend to retain each category of personal information — or the criteria used to determine that period — at or before the point of collection.
Among the nineteen US states with comprehensive privacy laws as of January 2026, only California requires disclosure of retention periods at the point of collection, and only Colorado’s CPA Rules mandate annual retention reviews. Virginia, Connecticut, Texas, and Oregon impose data minimization and purpose limitation duties but contain no explicit storage limitation principle equivalent to Article 5(1)(e). The gap between European and American approaches is narrowing, but for now, a WordPress site serving both EU and California consumers faces the strictest combined requirements: defined retention periods, disclosed at collection, technically enforced, and periodically reviewed.
Regulators have already fined their way through the argument that retention does not matter
The enforcement record on storage limitation is substantial, and it targets exactly the kind of passive over-retention that WordPress sites exhibit by default.
Deutsche Wohnen’s €14.5 million fine remains the seminal case. On-site inspections revealed that personal data of tenants across more than 160,000 apartments — salary statements, employment contracts, tax documents, health insurance records, bank statements — was stored in an archive system that could not delete data. The company had been warned in 2017 and by 2019 still could not demonstrate database cleansing capability. The CJEU later confirmed in Case C-807/21 that GDPR fines can be imposed directly on legal entities, closing the procedural escape route.
AG2R La Mondiale received a €1.75 million fine from CNIL in July 2021 for a subtler but more common violation. The French insurance group had defined retention periods on paper. The periods simply were not implemented in its systems. Over 2 million customers’ data — including health data and bank details — was retained beyond stated limits. Some 1.3 million health insurance records exceeded 10 years. Thousands exceeded 30 years. Having a policy you do not enforce is, in the eyes of CNIL, equivalent to having no policy at all.
The Digi Kft. case from Hungary established precedent directly relevant to anyone running WordPress staging environments with real user data. The telecoms provider created a test database containing personal data of approximately 322,000 subscribers for troubleshooting. After fixing the issue, the test database was not deleted for 18 months. The CJEU confirmed in Case C-77/21 (October 2022) that Article 5(1)(e) prohibits retention in a test database beyond the time necessary for the troubleshooting purpose. If you have ever cloned a production WordPress database to a staging site and left it there, this ruling applies to you.
CNIL has emerged as the most active enforcer. Carrefour France and Carrefour Banque received €3.05 million in combined fines in November 2020 for retaining data of 28 million inactive loyalty programme customers for 5-10 years. Spartoo SAS was fined €250,000 in July 2020 for retaining data of 3 million former customers for over five years — with CNIL ruling that opening a marketing email does not qualify as “last contact” to restart the retention clock. Discord received €800,000 for retaining 2.47 million French accounts inactive for over 3 years. In January 2026, CNIL fined Free Mobile and Free a combined €42 million, finding data relating to 2.8 million contracts cancelled for more than 10 years retained without justification.
The pattern is consistent across every case: regulators penalize not the existence of data that was improperly collected, but the continued existence of data whose purpose has expired.
What your WordPress database is actually doing
WordPress’s database architecture was designed for content persistence. Every major table retains data indefinitely absent manual intervention.
The wp_users and wp_usermeta tables store user accounts and associated metadata with no auto-deletion mechanism. The session_tokens meta key in wp_usermeta — a serialized array containing IP addresses, user agent strings, login timestamps, and session expiration — persists for expired sessions until the user logs in again. The wp_comments and wp_commentmeta tables retain all comments including five personal data fields per entry (author name, email, URL, IP address, user agent) with no automatic purging of any kind. Spam comments accumulate indefinitely unless you manually empty the spam folder.
The wp_posts table stores unlimited post revisions by default. The WP_POST_REVISIONS constant defaults to true, meaning every manual save creates a new revision row plus corresponding wp_postmeta entries. A site with 500 posts edited 20 times each generates over 10,000 revision rows. If custom post types store form submissions or user-generated content, revisions of those posts contain personal data multiplied by every save action.
The wp_options table accumulates bloat through transients — WordPress’s caching mechanism. Expired transients are cleaned only through lazy deletion (purged only when something requests them after expiry). WordPress added a daily delete_expired_transients() cron task in version 4.9, but it depends on WP-Cron firing reliably — which depends on site traffic, since WP-Cron is triggered by page loads, not a server-level cron. Documented cases include sites with 58,000 expired transients causing daily database crashes and 300MB of transient bloat. Transients set without an expiration value are stored permanently with autoload = 'yes', loading into memory on every page request.
The privacy tools introduced in WordPress 4.9.6 (May 2018) added personal data export and erasure — but these are entirely manual and request-based. There is no built-in mechanism to automatically delete data after a retention period expires. No scheduled purging. No time-based triggers. No retention policy configuration anywhere in the admin interface. WordPress 4.9.6 provided the infrastructure for responding to individual requests but nothing for systematic retention enforcement.
WooCommerce defaults to forever and hopes you will not notice
WooCommerce offers the most structured retention controls in the WordPress ecosystem, which makes it all the more remarkable that every setting ships configured for indefinite retention.
At WooCommerce → Settings → Accounts & Privacy → Personal Data Retention, five fields control automated cleanup: inactive accounts, pending orders, failed orders, cancelled orders, and completed orders. All five default to blank. Blank means indefinite. When configured, cleanup runs via a daily cron job. The distinction between how different order statuses are handled matters: completed orders are anonymized rather than deleted, preserving sales statistics while removing personal identifiers. The order becomes a “guest order” with personal fields replaced by [deleted]. Failed, pending, and cancelled orders are moved to trash and permanently deleted per EMPTY_TRASH_DAYS.
Beyond these five settings, WooCommerce creates substantial data stores with no built-in retention controls. The wp_woocommerce_sessions table stores guest shopper session data with a 48-hour default expiry, but cleanup depends on a cron hook firing reliably. On high-traffic stores, expired sessions accumulate to tens of thousands of rows — documented cases include 75,000 rows consuming 4.2 GB. The analytics tables (wp_wc_order_stats, wp_wc_order_product_lookup, wp_wc_customer_lookup) grow with every order and are never automatically pruned.
The Action Scheduler tables (wp_actionscheduler_actions and wp_actionscheduler_logs) present the most acute bloat problem. Used by WooCommerce, WPForms, WP Mail SMTP, MailPoet, and dozens of other plugins, these tables retain completed and cancelled actions for 30 days by default, cleaned in batches of 20 per minute. Failed actions are not cleaned at all by default. On high-traffic WooCommerce stores, these tables routinely reach hundreds of thousands of rows and multiple gigabytes, with the args column potentially containing email addresses, user IDs, and other personal data.
Plugins range from thoughtful to negligent
Contact Form 7 does not store submissions in the database by default — a privacy advantage. Its companion plugin Flamingo stores every submission as custom post types in wp_posts and wp_postmeta with no auto-delete capability, no retention settings, and no integration with WordPress’s core privacy tools. WPForms stores entries in custom tables but provides no built-in retention or auto-delete features. Gravity Forms stands alone with built-in per-form retention policies since version 2.4: under Form Settings → Personal Data → Retention Policy, administrators configure automatic trashing or deletion after a specified number of days. If you need a contact form plugin that respects storage limitation out of the box, Gravity Forms is currently the only major option that does.
Matomo for WordPress provides configurable data retention with separate settings for raw visit data and aggregated reports — raw data can be deleted while preserving anonymized statistics. Wordfence retains Live Traffic data with a configurable 1-30 day window (default 30) and, critically, its database tables persist after deactivation unless you explicitly enable “Delete Wordfence tables and data on deactivation.” Membership and LMS plugins — MemberPress, LearnDash, Paid Memberships Pro, LifterLMS — overwhelmingly default to indefinite retention with no automated cleanup mechanisms.
What defensible retention periods actually look like
No framework prescribes universal periods, but regulatory guidance and jurisdictional requirements establish defensible benchmarks.
Transaction and order data retention is driven by tax obligations. UK HMRC requires limited company records for 6 years. The US IRS general requirement is 3 years, extending to 7 years for bad debt deductions. German tax law requires 8 years (reduced from 10 in January 2025). For a WooCommerce store serving multiple jurisdictions, 7 years covers the longest common requirement. Configure completed order retention in WooCommerce to 7 years; the anonymization mechanism preserves financial data for tax compliance while removing personal identifiers.
Contact form submissions have no statutory retention requirement. A defensible period is 6-12 months. Analytics data should follow CNIL’s 13-month maximum for cookie-based analytics. Security and access logs should be retained for 6 months to 1 year. Inactive user accounts should be deleted or deactivated after 2 years of inactivity, based on CNIL’s guidance and its €800,000 fine against Discord for retaining accounts inactive for over 3 years. Email subscriber data should follow CNIL’s benchmark of 3 years from last genuine contact.
The technical work that closes the gap
Three wp-config.php constants address the most visible accumulation: define('WP_POST_REVISIONS', 5); limits stored revisions per post. define('EMPTY_TRASH_DAYS', 7); reduces trash auto-deletion from 30 days. define('AUTOSAVE_INTERVAL', 120); reduces autosave frequency. These prevent future accumulation but do not clean existing data.
For immediate cleanup, WP-CLI provides the necessary commands: wp post delete $(wp post list --post_type='revision' --format=ids) removes all existing revisions. wp transient delete --expired purges expired transients. wp comment delete $(wp comment list --status=spam --format=ids) clears spam. The wp-revisions-cli package adds wp revisions clean 5 to retain only five revisions per post.
Three filters control Action Scheduler bloat: action_scheduler_retention_period (reduce to 7 * DAY_IN_SECONDS), action_scheduler_default_cleaner_statuses (add failed to cleaned statuses), and action_scheduler_cleanup_batch_size (increase from 20 to 100).
For plugins without built-in retention — Flamingo being the most common offender — custom cron jobs bridge the gap. Register a daily scheduled event that runs a deletion query against submissions older than your defined retention period. Disable WP-Cron (define('DISABLE_WP_CRON', true);) and use a server-level cron to call wp-cron.php at regular intervals, because WP-Cron’s dependency on page views makes it unreliable for compliance-critical scheduled deletions.
An external object cache (Redis or Memcached) eliminates transient bloat entirely by storing transients in-memory with native TTL expiration rather than in the wp_options table. For orphaned metadata, direct SQL cleanup is necessary — delete entries from wp_postmeta and wp_commentmeta whose parent records no longer exist.
Backups are parallel data stores and regulators know it
Every backup contains a complete copy of all personal data at the moment of creation. When data is deleted from the live database, it persists in every backup taken before the deletion.
The ICO accepts that backup data may be placed “beyond use” — not actively processed, access restricted, overwritten in line with an established rotation schedule. But the controller must be “absolutely clear with individuals” about what happens to their data in backup systems. The EDPB’s 2025 Coordinated Enforcement Framework report identified backup erasure as one of seven systemic weaknesses across 764 surveyed controllers. Half of responding DPAs raised concerns that controllers have no specific procedures for handling erasure in the backup context.
The practical approach: daily backups retained 7-30 days, weekly backups 4-12 weeks, monthly backups 6-12 months maximum. Maintain a deletion registry logging all erasure and retention-based deletions, checked against data whenever a backup is restored. Encrypt all backups and restrict access to support the “beyond use” argument.
The gap between enforcement expectations and WordPress defaults is not narrowing on its own
Total GDPR fines reached approximately €6.7-7.1 billion by early 2026. The EDPB’s 4th Coordinated Enforcement Framework (March 2025) focused specifically on the right to erasure — a right whose effective exercise depends directly on controllers having defined retention periods. Thirty-two DPAs participated, nine opened formal investigations.
WordPress powers approximately 43% of all websites. Its default configurations are a de facto regulatory surface for nearly half the internet. The combination of indefinite default retention, manual-only privacy tools, plugin-dependent data scattered across custom tables, and backup-created parallel data stores means that a typical WordPress installation is non-compliant with storage limitation requirements from the moment it begins collecting user data.
Remember that blank stare from the opening? It is the same blank stare as those five empty WooCommerce retention fields. Both represent the same thing — an absence of thought about when data should stop existing. Deutsche Wohnen’s archive system could not delete data. Your WordPress database will not delete data. The difference is one of intent, not outcome, and regulators have shown no interest in distinguishing between the two.
— Comments 0
No comments yet. Be the first to share your opinion!
Comments are closed for this post.