|
| 1 | +#Data Retention |
| 2 | + |
| 3 | +Coder supports configurable retention policies that automatically purge old |
| 4 | +Audit Logs, Connection Logs, and API keys. These policies help manage database |
| 5 | +growth by removing records older than a specified duration. |
| 6 | + |
| 7 | +##Overview |
| 8 | + |
| 9 | +Large deployments can accumulate significant amounts of data over time. |
| 10 | +Retention policies help you: |
| 11 | + |
| 12 | +-**Reduce database size**: Automatically remove old records to free disk space. |
| 13 | +-**Improve performance**: Smaller tables mean faster queries and backups. |
| 14 | +-**Meet compliance requirements**: Configure retention periods that align with |
| 15 | + your organization's data retention policies. |
| 16 | + |
| 17 | +>[!NOTE] |
| 18 | +>Retention policies are disabled by default (set to`0`) to preserve existing |
| 19 | +>behavior. The only exception is API keys, which defaults to 7 days. |
| 20 | +
|
| 21 | +##Configuration |
| 22 | + |
| 23 | +You can configure retention policies using CLI flags, environment variables, or |
| 24 | +a YAML configuration file. |
| 25 | + |
| 26 | +###Settings |
| 27 | + |
| 28 | +| Setting| CLI Flag| Environment Variable| Default| Description| |
| 29 | +| ---------------| -----------------------------| ---------------------------------| ----------------| -------------------------------------------------------------------------| |
| 30 | +| Global|`--global-retention`|`CODER_GLOBAL_RETENTION`|`0` (disabled)| Default retention for all data types. Individual settings override this.| |
| 31 | +| Audit Logs|`--audit-logs-retention`|`CODER_AUDIT_LOGS_RETENTION`|`0` (use global)| How long to retain Audit Log entries.| |
| 32 | +| Connection Logs|`--connection-logs-retention`|`CODER_CONNECTION_LOGS_RETENTION`|`0` (use global)| How long to retain Connection Log entries.| |
| 33 | +| API Keys|`--api-keys-retention`|`CODER_API_KEYS_RETENTION`|`7d`| How long to retain expired API keys.| |
| 34 | + |
| 35 | +###Duration Format |
| 36 | + |
| 37 | +Retention durations use Go's duration format: |
| 38 | + |
| 39 | +-`24h` - 24 hours |
| 40 | +-`168h` - 7 days |
| 41 | +-`720h` - 30 days |
| 42 | +-`2160h` - 90 days |
| 43 | +-`8760h` - 365 days |
| 44 | + |
| 45 | +###CLI Example |
| 46 | + |
| 47 | +```bash |
| 48 | +coder server \ |
| 49 | + --global-retention=2160h \ |
| 50 | + --audit-logs-retention=8760h \ |
| 51 | + --api-keys-retention=168h |
| 52 | +``` |
| 53 | + |
| 54 | +###Environment Variables Example |
| 55 | + |
| 56 | +```bash |
| 57 | +export CODER_GLOBAL_RETENTION=2160h |
| 58 | +export CODER_AUDIT_LOGS_RETENTION=8760h |
| 59 | +export CODER_API_KEYS_RETENTION=168h |
| 60 | +``` |
| 61 | + |
| 62 | +###YAML Configuration Example |
| 63 | + |
| 64 | +```yaml |
| 65 | +retention: |
| 66 | +global:2160h |
| 67 | +audit_logs:8760h |
| 68 | +connection_logs:0s |
| 69 | +api_keys:168h |
| 70 | +``` |
| 71 | +
|
| 72 | +## How Retention Works |
| 73 | +
|
| 74 | +### Background Purge Process |
| 75 | +
|
| 76 | +Coder runs a background process that periodically deletes old records. The |
| 77 | +purge process: |
| 78 | +
|
| 79 | +1. Runs approximately every 10 minutes. |
| 80 | +2. Processes records in batches to avoid database lock contention. |
| 81 | +3. Deletes records older than the configured retention period. |
| 82 | +4. Logs the number of deleted records for monitoring. |
| 83 | +
|
| 84 | +### Effective Retention |
| 85 | +
|
| 86 | +For each data type, the effective retention is determined as follows: |
| 87 | +
|
| 88 | +1. If the individual setting is non-zero, use that value. |
| 89 | +2. If the individual setting is zero, use the global retention value. |
| 90 | +3. If both are zero, retention is disabled (data is kept indefinitely). |
| 91 | +
|
| 92 | +### API Keys Special Behavior |
| 93 | +
|
| 94 | +API key retention only affects **expired** keys. A key is deleted only when: |
| 95 | +
|
| 96 | +1. The key has expired (past its`expires_at` timestamp). |
| 97 | +2. The key has been expired for longer than the retention period. |
| 98 | + |
| 99 | +Setting `--api-keys-retention=7d` deletes keys that expired more than 7 days |
| 100 | +ago. Active keys are never deleted by the retention policy. |
| 101 | + |
| 102 | +Keeping expired keys for a short period allows Coder to return a more helpful |
| 103 | +error message when users attempt to use an expired key. |
| 104 | + |
| 105 | +## Best Practices |
| 106 | + |
| 107 | +### Recommended Starting Configuration |
| 108 | + |
| 109 | +For most deployments, we recommend: |
| 110 | + |
| 111 | +```yaml |
| 112 | +retention: |
| 113 | + global: 2160h # 90 days |
| 114 | + audit_logs: 8760h # 1 year |
| 115 | + connection_logs: 0s # Use global |
| 116 | + api_keys: 168h # 7 days |
| 117 | +``` |
| 118 | + |
| 119 | +### Compliance Considerations |
| 120 | + |
| 121 | +> [!WARNING] |
| 122 | +> Audit Logs provide critical security and compliance information. Purging |
| 123 | +> Audit Logs may impact your organization's ability to investigate security |
| 124 | +> incidents or meet compliance requirements. Consult your security and |
| 125 | +> compliance teams before configuring Audit Log retention. |
| 126 | + |
| 127 | +Common compliance frameworks have varying retention requirements: |
| 128 | + |
| 129 | +- **SOC 2**: Typically requires 1 year of audit logs. |
| 130 | +- **HIPAA**: Requires 6 years for certain records. |
| 131 | +- **PCI DSS**: Requires 1 year of audit logs, with 3 months immediately |
| 132 | +available. |
| 133 | +- **GDPR**: Requires data minimization but does not specify maximum retention. |
| 134 | + |
| 135 | +### External Log Aggregation |
| 136 | + |
| 137 | +If you use an external log aggregation system (Splunk, Datadog, etc.), you can |
| 138 | +configure shorter retention periods in Coder since logs are preserved |
| 139 | +externally. See |
| 140 | +[Capturing/Exporting Audit Logs](../security/audit-logs.md#capturingexporting-audit-logs) |
| 141 | +for details on exporting logs. |
| 142 | + |
| 143 | +### Database Maintenance |
| 144 | + |
| 145 | +After enabling retention policies, you may want to run a `VACUUM` operation on |
| 146 | +your PostgreSQL database to reclaim disk space. See |
| 147 | +[Maintenance Procedures](../security/audit-logs.md#maintenance-procedures-for-the-audit-logs-table) |
| 148 | +for guidance. |
| 149 | + |
| 150 | +## Disabling Retention |
| 151 | + |
| 152 | +Setting a retention value to `0` means "use global retention", not "disable". |
| 153 | +To disable all automatic purging, set global to `0` and leave individual |
| 154 | +settings at `0`: |
| 155 | + |
| 156 | +```yaml |
| 157 | +retention: |
| 158 | + global: 0s |
| 159 | + audit_logs: 0s |
| 160 | + connection_logs: 0s |
| 161 | + api_keys: 0s |
| 162 | +``` |
| 163 | + |
| 164 | +There is no way to disable retention for a specific data type while global |
| 165 | +retention is enabled. If you need to retain one data type longer than others, |
| 166 | +set its individual retention to a larger value. |
| 167 | + |
| 168 | +## Monitoring |
| 169 | + |
| 170 | +The purge process logs deletion counts at the `DEBUG` level. To monitor |
| 171 | +retention activity, enable debug logging or search your logs for entries |
| 172 | +containing the table name (e.g., `audit_logs`, `connection_logs`, `api_keys`). |
| 173 | + |
| 174 | +## Related Documentation |
| 175 | + |
| 176 | +-[Audit Logs](../security/audit-logs.md):Learn about Audit Logs and manual |
| 177 | +purge procedures. |
| 178 | +-[Connection Logs](../monitoring/connection-logs.md):Learn about Connection |
| 179 | +Logs and monitoring. |