Data Retention and Archival Policies
Arbitex retention policies control how long platform data is kept before automatic deletion. Each policy targets a specific table and specifies a retention window in days. A background garbage-collection service evaluates all enabled policies on a scheduled basis and deletes expired rows.
Retention policy fields
Section titled “Retention policy fields”| Field | Type | Description |
|---|---|---|
table_name | string | Target table (e.g. "audit_logs", "usage_records") |
retention_days | int | Records older than this many days are eligible for deletion |
enabled | bool | Whether the policy runs during scheduled GC cycles |
Each table may have at most one policy per tenant. Creating a second policy for the same table returns 409 Conflict.
Retention-eligible tables
Section titled “Retention-eligible tables”| Table | Contents | Typical retention |
|---|---|---|
audit_logs | Request/response audit events | 90–365 days |
usage_records | Per-user token/cost usage | 90–365 days |
alert_history | Alert trigger history | 30–90 days |
dlp_events | DLP scan results | 90–180 days |
compliance_reports | Compliance export bundles | 365 days |
Managing retention policies
Section titled “Managing retention policies”Create a policy
Section titled “Create a policy”POST /api/admin/retention-policiesAuthorization: Bearer <admin-token>Content-Type: application/json{ "table_name": "audit_logs", "retention_days": 90, "enabled": true}Response 201 Created
{ "id": "policy-uuid-...", "table_name": "audit_logs", "retention_days": 90, "enabled": true, "last_run_at": null, "records_deleted_last_run": null, "created_at": "2026-03-12T00:00:00Z", "updated_at": "2026-03-12T00:00:00Z"}Error — duplicate policy
{ "detail": "Retention policy for table 'audit_logs' already exists"}List policies
Section titled “List policies”GET /api/admin/retention-policiesAuthorization: Bearer <admin-token>Returns all configured policies, ordered by creation date (newest first). The last_run_at and records_deleted_last_run fields reflect the most recent GC run.
Get a policy
Section titled “Get a policy”GET /api/admin/retention-policies/{policy_id}Authorization: Bearer <admin-token>Update a policy
Section titled “Update a policy”PUT /api/admin/retention-policies/{policy_id}Authorization: Bearer <admin-token>Partial update — only provided fields are modified.
{ "retention_days": 180, "enabled": false}Use enabled: false to pause a policy without deleting it (e.g. during compliance audits where you need to preserve records beyond the normal window).
Delete a policy
Section titled “Delete a policy”DELETE /api/admin/retention-policies/{policy_id}Authorization: Bearer <admin-token>Deletes the policy configuration. Existing data is unaffected — no deletion is triggered. Returns 204 No Content.
Dry-run preview
Section titled “Dry-run preview”Before triggering a cleanup, preview how many records would be deleted:
GET /api/admin/retention-policies/{policy_id}/previewAuthorization: Bearer <admin-token>Response 200 OK
{ "policy_id": "policy-uuid-...", "table_name": "audit_logs", "retention_days": 90, "records_to_delete": 14328, "oldest_record_date": "2025-10-15T08:22:00Z"}Use this before running a manual cleanup to confirm the deletion scope. The oldest_record_date reflects the earliest record in the table regardless of age, so you can confirm no unexpectedly old data exists.
Manual cleanup
Section titled “Manual cleanup”Run a single policy
Section titled “Run a single policy”POST /api/admin/retention-policies/{policy_id}/runAuthorization: Bearer <admin-token>Immediately runs the cleanup for the specified policy and returns the result:
{ "table_name": "audit_logs", "records_deleted": 14328, "ran_at": "2026-03-12T14:00:00Z"}Run all enabled policies
Section titled “Run all enabled policies”POST /api/admin/retention-policies/run-allAuthorization: Bearer <admin-token>Runs cleanup for every enabled policy within the tenant and returns an array of per-table results:
[ { "table_name": "audit_logs", "records_deleted": 14328, "ran_at": "2026-03-12T14:00:00Z" }, { "table_name": "usage_records", "records_deleted": 3210, "ran_at": "2026-03-12T14:00:05Z" }]Each run updates the last_run_at and records_deleted_last_run fields on the policy record for observability.
Scheduled GC
Section titled “Scheduled GC”The platform runs a scheduled garbage-collection job that evaluates all enabled policies for the tenant. The job:
- Queries all enabled policies for the tenant
- For each policy, deletes rows from the target table where the record timestamp is older than
retention_days - Updates
last_run_atandrecords_deleted_last_run - Writes a summary entry to the admin audit log
The GC schedule is controlled by platform operators and is typically daily (00:00 UTC).
Compliance considerations
Section titled “Compliance considerations”Minimum retention requirements
Section titled “Minimum retention requirements”Several compliance frameworks impose minimum retention periods:
| Framework | Requirement |
|---|---|
| SOC 2 | Audit logs ≥ 1 year |
| PCI-DSS | Access logs ≥ 1 year, archived ≥ 3 years |
| HIPAA | PHI access logs ≥ 6 years |
| GDPR | Must delete upon data subject request (right to erasure) |
Set retention_days to match or exceed the minimum for your compliance posture. For frameworks with long archival requirements (PCI-DSS 3-year archive), export compliance bundles via GET /api/admin/compliance-export before the GC cycle deletes the data.
Right to erasure (GDPR Article 17)
Section titled “Right to erasure (GDPR Article 17)”Retention policies handle time-based deletion but not identity-based deletion. For GDPR right-to-erasure requests, use the user deletion workflow in the admin console, which removes all personal data for a specific user across all tables regardless of retention policy settings.
Pausing for audits
Section titled “Pausing for audits”If a compliance audit requires preserving data beyond the normal retention window:
- Set the relevant policies to
enabled: false - Document the pause reason in the admin audit log
- Re-enable after the audit is complete
Disabled policies are not evaluated during scheduled GC runs.