--- title: "Retention settings and report" description: "What the Drupal server stores per run, how to see it, and how the retention policy is declared." source: https://flowdrop.io/docs/drupal/retention site: FlowDrop documentation --- # Retention settings and report {/* Claims on this page were read from apps/fddo (branch feature/26-stable-closeout): config/install/flowdrop.settings.yml — the retention: group and its defaults config/schema/flowdrop.schema.yml — flowdrop.retention_policy, flowdrop.retention_policy_age_only src/Retention/RetentionInfo.php — the declared entity types and their kinds src/Retention/RetentionInfoInterface.php — KIND_POLICY / KIND_EXISTING_CLEANUP / KIND_TTL src/Retention/RetentionRow.php — the meaning of each report column src/Retention/RetentionReport.php — the cached report service src/Drush/Commands/RetentionCommands.php — flowdrop:retention:report, its fields and caveats src/Hook/RequirementsHooks.php — the status-report line; "there is no administration page" src/Hook/CronHooks.php — the daily read-only warm CHANGELOG.md [2.6.0-alpha2], [2.6.0-alpha3] "Removed: the retention mode slim" UPGRADE.md "New: data retention settings and report", "Removed: the retention mode slim" */} Every workflow run leaves rows behind: a pipeline, a job per node, and — when the run came from a chat or the Playground — a session and its messages. FlowDrop declares what it keeps, measures it, and reports on it. **Nothing is deleted.** There is no sweeper, no cron cleanup and no purge command for the governed types. Both retention modes behave identically today; `delete` is accepted so a later release can honour it without a configuration migration. Setting a mode changes only what the report says. ## Where the settings live The policy is configuration on `flowdrop.settings`, under a `retention` group. There is no administration page for it — read and write it like any other configuration: ```bash drush config:get flowdrop.settings retention drush config:set flowdrop.settings retention.flowdrop_job.max_age 604800 ``` The group ships with the module and is stamped onto existing sites by `flowdrop_post_update_add_retention_settings()`, which writes absent keys only, so a value you already chose survives. ## What each type declares One block per governed entity type, each with a `mode` and one or two age thresholds: | Key | Default | What it governs | | --- | --- | --- | | `retention..mode` | `off` | `off` or `delete`. | | `retention..max_age` | `2592000` (30 days) | Age in seconds after which a success-like terminal row would become eligible. `0` means every such row. | | `retention..failure_max_age` | `31536000` (365 days) | The same for failure-like terminal rows. Normally longer: a failed run is the one you still want to read next quarter. | `` is one of `flowdrop_session`, `flowdrop_pipeline`, `flowdrop_job`, `flowdrop_session_message` and `state_checkpoint`. `state_checkpoint` carries no status field, so age is the only criterion there: it takes `mode` and `max_age`, and has no `failure_max_age`. **Every type ships `mode: off`**, and `off` is a supported, legitimate state — a site that keeps every run forever is doing nothing wrong. ### The two modes - **`off`** — keep everything. - **`delete`** — accepted by the configuration schema and reserved for a later release. It validates, and today it behaves exactly as `off`. A third mode, `slim`, was accepted by an earlier alpha and has been withdrawn. It is gone from the schema, and `flowdrop_post_update_drop_slim_retention_mode()` rewrites a stored `slim` to `off` when you run `drush updatedb`. Run the update: a site that still stores `slim` fails strict configuration validation, so `drush config:inspect` and configuration imports both complain. ### What is never eligible Only terminal rows are ever counted as eligible. A row that is `paused`, `pending`, `running`, `idle`, `awaiting_input` or `interrupted` is not terminal and no setting makes it eligible. ## Reading the report ```bash drush flowdrop:retention:report # the cached report drush flowdrop:retention:report --refresh # recompute every count and size first ``` The alias is `fd:retention:report`. The command is read-only: it deletes nothing, and since nothing else deletes anything either, **this is the dry run**. Seven columns are shown by default: | Column | Field | What it means | | --- | --- | --- | | Type | `type` | The entity type id. | | Mode | `mode` | The configured mode for that type. | | Rows | `rows` | Total stored rows. | | Size | `bytes` | Base table plus dedicated field tables, data and index length. Not measured off MySQL/MariaDB. | | Oldest | `oldest` | Age of the oldest row, in whole days. | | Eligible (ok) | `eligible_success` | Success-like terminal rows older than `max_age`. | | Eligible (fail) | `eligible_failure` | Failure-like terminal rows older than `failure_max_age`. | Five more are available through `--fields`: `kind` (whether FlowDrop governs the type, another module's cron already sweeps it, or its lifetime is an expiry stamp), `excluded` (rows held by a non-terminal status, which no policy could ever match), `reclaim` (bytes pro-rated across the eligible share of rows), `policy` (what already governs a store FlowDrop does not) and `error` (why a row could not be measured). ```bash drush flowdrop:retention:report --fields=type,kind,excluded,reclaim,policy drush flowdrop:retention:report --format=json ``` A structured format always carries every column as raw numbers — bytes, unix timestamps, integer counts — so you can do arithmetic on them instead of parsing `198.7 MB` back into bytes. A dash in the table means *not measured*, which is not the same as zero. The report also accounts for the stores FlowDrop does **not** govern — interrupts, workflow snapshots and memory records — so one place accounts for everything the module deletes. Those keep their own cron cleanups and TTL, and their eligibility follows that sweeper's own rules: a cancelled snapshot is never reported as reclaimable. ## The status report line Drupal's status report carries a **FlowDrop data retention** line. It is informational, never a warning, and it only ever reads the cached report — measuring scans every runtime table, which is never done while rendering a page. Cron builds the report once a day, a read-only warm that measures and caches and deletes nothing, and rebuilds it on the next run whenever the cache is empty. So a cache rebuild costs one cron interval rather than a day. Until the first build the line reads *Not yet computed* and names `drush flowdrop:retention:report --refresh`. This is an operational size-and-age report, **not** a GDPR erasure mechanism. It makes no claim about personal data and offers no subject-level deletion.