Normalizes non-standard code-fence language tags across `docs/**` so a strict highlighter (Shiki, used by Fumadocs) won't fail the build on an unrecognized language, and unifies redundant synonym tags onto one canonical form per language. The current renderer (Speed-Highlight) detects the language from the code content, not the fence label, so this drift wasn't visible until now. ## Changes - `hcl` -> `tf` (199 fences, including indented ones nested in numbered/bulleted lists). Shiki ships `hcl` and `terraform` as two distinct grammars (not aliases); every `hcl`-tagged fence in `docs/**` is actually Terraform resource/data/provider syntax, so the more specific `terraform` grammar is correct for all of them. `tf` is Shiki's own alias for that grammar, and it's also what GitHub's own markdown renderer resolves to the same HCL/Terraform highlighting. - `pwsh`/`powershell` -> `ps1`. Both `ps` and `ps1` are registered PowerShell aliases in Shiki, but on GitHub's renderer only `.ps1` is a registered file extension (`.ps` isn't), so `ps1` renders identically to `powershell` there today while bare `ps` would silently lose highlighting. - `env` -> `dotenv` (a dedicated Shiki grammar for `KEY=VALUE` files) - `text`/`output`/`none`/`url` -> `txt`. Same built-in plain-text fallback either way, just shorter. - `Dockerfile` -> `dockerfile` (lowercase) - `bash`/`shell` -> `sh` (732 fences). Shiki and GitHub both alias all three to a single shell grammar; this was already the style guide's stated preference, just not enforced across the existing corpus until now. - `markdown` -> `md` (4 fences). Alias of the same grammar in both Shiki and GitHub. - `jsonc` -> `json` (1 fence). The block has no comments or trailing commas, so it doesn't need the comments-capable grammar. - `ts` -> `tsx` (2 fences, `docs/about/contributing/frontend.md`). Verified the actual content tokenizes identically under both grammars, and a sibling block in the same file already needs `tsx` for real JSX, so unifying to one tag is safe for this file. Documented a caveat: `tsx` mis-tokenizes the legacy angle-bracket type-assertion syntax (`<Type>value`), which is invalid in real `.tsx` files anyway, so use `value as Type` instead. - `yml` -> `yaml` (1 fence) - Updated `docs/.style/style-guide/formatting.md` to document all canonical tags `promql` (2 fences) and `caddyfile` (2 fences) are left as-is. Shiki doesn't bundle a grammar for either, so they need a custom grammar registration when the site adopts Shiki, rather than degrading to `txt`. Tracked as follow-up work under DOCS-118 and [DOCS-544](https://linear.app/codercom/issue/DOCS-544/vendor-a-local-promql-grammar-for-shiki-syntax-highlighting) (promql). Does not touch `offlinedocs/`. Linear: [DOCS-476](https://linear.app/codercom/issue/DOCS-476/normalize-docs-code-fence-languages-de-risk-shikifumadocs) <details> <summary>How the fence tags were verified</summary> Each tag was tested against a real `shiki@latest` highlighter instance (`codeToHtml`/`codeToTokens`) and cross-checked against GitHub's `@wooorm/starry-night` grammar sources (the renderer that actually displays these `.md` files today, in repo browsing and PR diffs), since that's what determines whether brevity is safe before Shiki adoption: ```text FAIL env -- Language `env` is not included in this bundle. FAIL Dockerfile -- Language `Dockerfile` is not included in this bundle. FAIL promql -- Language `promql` is not included in this bundle. FAIL caddyfile -- Language `caddyfile` is not included in this bundle. FAIL pwsh -- Language `pwsh` is not included in this bundle. FAIL output -- Language `output` is not included in this bundle. ``` `hcl` doesn't error in Shiki, since it's a real grammar, but that's exactly the trap: it was silently rendering every fence with the generic HCL grammar instead of the Terraform-specific one. Every `hcl`-tagged fence in `docs/**` was manually checked against `origin/main` and is genuinely Terraform content. For `ts`/`tsx`, tokenizing the actual doc content confirmed identical output under both grammars; a synthetic test with the legacy angle-bracket cast syntax confirmed `tsx` degrades on that specific construct, which the style guide now calls out. The first normalization pass only matched fence tags at column 0 (`^```tag$`), missing tags indented inside numbered/bulleted lists. A follow-up pass caught the remaining occurrences at any indentation level. </details> --- *This PR description and the underlying changes were prepared with Coder Agents assistance.*
7.8 KiB
Data Retention
Coder supports configurable retention policies that automatically purge old Audit Logs, Connection Logs, Workspace Agent Logs, API keys, and AI Gateway records. These policies help manage database growth by removing records older than a specified duration.
Overview
Large deployments can accumulate significant amounts of data over time. Retention policies help you:
- Reduce database size: Automatically remove old records to free disk space.
- Improve performance: Smaller tables mean faster queries and backups.
- Meet compliance requirements: Configure retention periods that align with your organization's data retention policies.
Note
Retention policies are disabled by default (set to
0) to preserve existing behavior. The exceptions are API keys and workspace agent logs, which default to 7 days.
Configuration
You can configure retention policies using CLI flags, environment variables, or a YAML configuration file.
Settings
| Setting | CLI Flag | Environment Variable | Default | Description |
|---|---|---|---|---|
| Audit Logs | --audit-logs-retention |
CODER_AUDIT_LOGS_RETENTION |
0 (disabled) |
How long to retain Audit Log entries |
| Connection Logs | --connection-logs-retention |
CODER_CONNECTION_LOGS_RETENTION |
0 (disabled) |
How long to retain Connection Logs |
| API Keys | --api-keys-retention |
CODER_API_KEYS_RETENTION |
7d |
How long to retain expired API keys |
| Workspace Agent Logs | --workspace-agent-logs-retention |
CODER_WORKSPACE_AGENT_LOGS_RETENTION |
7d |
How long to retain workspace agent logs |
| AI Gateway | --ai-gateway-retention |
CODER_AI_GATEWAY_RETENTION |
60d |
How long to retain AI Gateway records |
Note
AI Gateway retention is configured separately from other retention settings. See AI Gateway Setup for detailed configuration options.
Duration Format
Retention durations support days (d) and weeks (w) in addition to standard
Go duration units (h, m, s):
7d- 7 days2w- 2 weeks30d- 30 days90d- 90 days365d- 1 year
CLI Example
coder server \
--audit-logs-retention=365d \
--connection-logs-retention=90d \
--api-keys-retention=7d \
--workspace-agent-logs-retention=7d \
--ai-gateway-retention=60d
Environment Variables Example
export CODER_AUDIT_LOGS_RETENTION=365d
export CODER_CONNECTION_LOGS_RETENTION=90d
export CODER_API_KEYS_RETENTION=7d
export CODER_WORKSPACE_AGENT_LOGS_RETENTION=7d
export CODER_AI_GATEWAY_RETENTION=60d
YAML Configuration Example
retention:
audit_logs: 365d
connection_logs: 90d
api_keys: 7d
workspace_agent_logs: 7d
ai_gateway:
retention: 60d
How Retention Works
Background Purge Process
Coder runs a background process that periodically deletes old records. The purge process:
- Runs approximately every 10 minutes.
- Processes records in batches to avoid database lock contention.
- Deletes records older than the configured retention period.
- Logs the number of deleted records for monitoring.
Effective Retention
Each retention setting controls its data type independently:
- When set to a non-zero duration, records older than that duration are deleted.
- When set to
0, retention is disabled and data is kept indefinitely.
API Keys Special Behavior
API key retention only affects expired keys. A key is deleted only when:
- The key has expired (past its
expires_attimestamp). - The key has been expired for longer than the retention period.
Setting --api-keys-retention=7d deletes keys that expired more than 7 days
ago. Active keys are never deleted by the retention policy.
Keeping expired keys for a short period allows Coder to return a more helpful error message when users attempt to use an expired key.
Workspace Agent Logs Behavior
Workspace agent logs are deleted based on when the agent last connected, not the age of the logs themselves. Logs from the latest build of each workspace are always retained regardless of when the agent last connected. This ensures you can always debug issues with active workspaces.
For non-latest builds, logs are deleted if the agent hasn't connected within the
retention period. Setting --workspace-agent-logs-retention=7d deletes logs for
agents that haven't connected in 7 days (excluding those from the latest build).
AI Gateway Data Behavior
AI Gateway retention applies to interception records and all related data, including token usage, prompts, and tool invocations. The default of 60 days provides a reasonable balance between storage costs and the ability to analyze usage patterns.
For details on what data is retained, see the AI Gateway Data Retention documentation.
Best Practices
Recommended Starting Configuration
For most deployments, we recommend:
retention:
audit_logs: 365d
connection_logs: 90d
api_keys: 7d
workspace_agent_logs: 7d
ai_gateway:
retention: 60d
Compliance Considerations
Warning
Audit Logs provide critical security and compliance information. Purging Audit Logs may impact your organization's ability to investigate security incidents or meet compliance requirements. Consult your security and compliance teams before configuring Audit Log retention.
Common compliance frameworks have varying retention requirements:
- SOC 2: Typically requires 1 year of audit logs.
- HIPAA: Requires 6 years for certain records.
- PCI DSS: Requires 1 year of audit logs, with 3 months immediately available.
- GDPR: Requires data minimization but does not specify maximum retention.
External Log Aggregation
If you use an external log aggregation system (Splunk, Datadog, etc.), you can configure shorter retention periods in Coder since logs are preserved externally. See Capturing/Exporting Audit Logs for details on exporting logs.
Database Maintenance
After enabling retention policies, you may want to run a VACUUM operation on
your PostgreSQL database to reclaim disk space. See
Maintenance Procedures
for guidance.
Keeping Data Indefinitely
To keep data indefinitely for any data type, set its retention value to 0:
retention:
audit_logs: 0s # Keep audit logs forever
connection_logs: 0s # Keep connection logs forever
api_keys: 0s # Keep expired API keys forever
workspace_agent_logs: 0s # Keep workspace agent logs forever
ai_gateway:
retention: 0s # Keep AI Gateway records forever
Monitoring
The purge process logs deletion counts at the DEBUG level. To monitor
retention activity, enable debug logging or search your logs for entries
containing the table name (e.g., audit_logs, connection_logs, api_keys).
Related Documentation
- Audit Logs: Learn about Audit Logs and manual purge procedures.
- Connection Logs: Learn about Connection Logs and monitoring.
- AI Gateway: Learn about AI Gateway for centralized LLM and MCP proxy management.
- AI Gateway Setup: Configure AI Gateway data retention.
- AI Gateway Monitoring: Monitor AI Gateway usage and metrics.