Skip to content

[Feature Request] Support Automatic Audit Log Archiving and Retention Policies #3556

Description

@z8hh

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed. / 请使用英语提交,否则会被关闭。
  • Please do not modify this template :) and fill in all the required fields.

1. Is this request related to a challenge you're experiencing? Tell me about your story.

Feature Request

It would be very useful if Cloudreve could add lifecycle management and automatic archiving for Audit Logs / Events.

Currently, audit and event records are continuously stored in the main database table, such as audit_logs.

For long-running instances with a large number of downloads, direct-link accesses, shared-link accesses, and other operations, the audit log table can grow very quickly.

In one real production instance, we currently have approximately:

Audit log records: ~80 million rows
Total database size: ~30 GB

A large portion of the database size is caused by historical audit records, including download events, file reads, direct-link accesses, shared-link accesses, IP addresses, request IDs, and other activity records.

These logs are valuable for auditing, security investigations, and historical access tracking, but keeping all of them permanently inside the main Cloudreve database creates several problems.

Current Problems

When audit_logs grows to tens of millions or even hundreds of millions of rows, it significantly increases:

Full database backup time
Database restore time
Database migration time
MySQL storage usage
Index maintenance cost
Database cleanup cost
Migration and replication workload

For example, during a recent database migration, most of the core Cloudreve tables containing users, files, shares, storage configuration, and other business data could be migrated relatively quickly.

However, the audit log table contained tens of millions of rows and became one of the largest bottlenecks in the entire migration process.

The core Cloudreve business data itself was not very large, but the large amount of historical audit data caused the whole database to become unnecessarily difficult to back up, migrate, and maintain.

Suggested Solution: Online Logs + Automatic Archive

It would be useful to introduce an Audit Log Lifecycle / Audit Log Archive feature.

Administrators could configure how long audit logs remain online in MySQL.

For example:

Audit log database retention:

30 days
90 days
180 days
365 days
Forever
Custom

If the administrator selects:

Database retention: 90 days

then the most recent 90 days of audit logs would remain in the audit_logs table and continue to be searchable normally from the Cloudreve admin interface.

Logs older than 90 days could automatically enter an archive process:

audit_logs

Find records older than the configured retention period

Export by month

Compress

Upload to archive storage

Verify archive integrity

Delete the corresponding historical rows from MySQL

This would keep the main database at a relatively stable size instead of allowing audit logs to grow indefinitely.

Support S3-Compatible Storage for Archives

It would be very useful if archived logs could be stored using an existing Cloudreve storage policy or a separately configured S3-compatible storage destination.

For example:

Audit Log Archive

Automatic archive: Enabled

Online database retention:
90 days

Archive interval:
Monthly

Archive storage:
S3-compatible storage

Archive format:
CSV.gz
JSON.gz
Parquet
SQL.gz

Archive retention:
180 days
365 days
Forever

An archive directory could look like:

audit-logs/
└── 2026/
├── 01/
│ └── audit_logs_2026-01.csv.gz
├── 02/
│ └── audit_logs_2026-02.csv.gz
├── 03/
│ └── audit_logs_2026-03.csv.gz
└── ...

Object storage is much more suitable for low-frequency, long-term historical audit data than keeping all records permanently in the primary MySQL database.

Archive Integrity Verification

To avoid accidental data loss, Cloudreve should only delete the original database records after the entire archive operation has been successfully completed.

A safe workflow could be:

Export completed

Compression completed

Upload completed

Archive file integrity verified

Record count verified

Delete archived rows from MySQL

Each archive file could also have metadata such as:

Start time
End time
Number of records
Compressed file size
SHA256 checksum
Archive creation time
Archive status

Example:

Archive:
2026-01

Records:
12,580,321

File:
audit_logs_2026-01.csv.gz

SHA256:
xxxxxxxxxxxxxxxx

Status:
Archived
Batched Database Cleanup

If there are tens of millions of old audit records, it would be better not to execute one very large statement such as:

DELETE FROM audit_logs
WHERE created_at < ...;

Deleting tens of millions of rows in one transaction can cause:

Very large transactions
Significant Binlog growth
High disk I/O
Lock contention
Replication lag
Increased database load
DTS or other replication delays

It would be safer if Cloudreve deleted archived records in batches, for example:

Delete 5,000–50,000 rows

COMMIT

Continue with the next batch

The cleanup speed could also be configurable so that archival cleanup does not significantly affect normal Cloudreve traffic.

Optional: Time-Based Partitioning

If implementation complexity allows, it may also be worth considering time-based partitioning for audit_logs.

For example:

2026-01
2026-02
2026-03
2026-04
...

After a historical month has been successfully archived, the corresponding partition could be removed directly.

For extremely large audit tables, dropping an old partition can be much more efficient than deleting millions of rows individually.

Historical Archive Access

It would also be useful if the admin interface could distinguish between online and archived logs.

For example:

Events

Recent 90 days
→ Query directly from MySQL

Historical archives
→ 2026-01
→ 2026-02
→ 2026-03

Recent audit logs would remain fast and searchable.

If an administrator needs to investigate older activity, the corresponding archive could be downloaded, restored temporarily, or queried through a separate historical log viewer.

Why Not Simply Use a Second Database?

Another possible solution would be to move audit_logs into a second database.

However, if both databases are still hosted on the same MySQL instance:

cloudreve
cloudreve_logs

the total:

Disk usage
Backup size
MySQL instance size
Migration workload

would not actually decrease very much.

If the audit database is moved to a completely separate MySQL server, this also introduces additional complexity:

A second database connection pool
A second backup system
Additional high-availability requirements
Cross-database relationships
Additional failure scenarios

For most Cloudreve deployments, keeping recent logs in the main database while automatically archiving historical logs to object storage may be a simpler and more generally useful solution.

Expected Benefits

This feature could:

Prevent audit_logs from growing indefinitely
Significantly reduce the size of the main Cloudreve database
Reduce database backup time
Reduce database restore time
Improve database migration efficiency
Reduce RDS / DTS migration workloads
Lower MySQL storage costs
Preserve historical download, sharing, and access audit records
Allow administrators to configure log retention according to their operational or compliance requirements
Greatly improve maintainability for high-traffic Cloudreve instances

In our current production case, the database has already reached approximately:

~80 million audit/event records
~30 GB total database size

and the number continues to grow with normal traffic.

It would be very helpful if Cloudreve could support an Audit Log Lifecycle / Archive mechanism so that historical audit logs can be automatically archived instead of remaining permanently inside the primary application database.

2. Additional context or comments

No response

3. Can you help us with this feature?

  • I am interested in contributing to this feature.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions