Skip to main content

Audit logs

On this page

Audit Logs allows Auditors to monitor user operations in their deployment.

Note

Audit logs require a Premium license. For more details, contact your account team.

Tracked Events

Coder records audit log entries for the resources below. Each section lists the actions that produce an entry, followed by the resource's fields. When a tracked field changes, the change appears in the entry's diff, and untracked fields are left out.

AIGatewayKey

Actions: create, delete

FieldTracked
created_atNo
hashed_secretYes
idYes
last_heartbeat_atNo
nameYes
secret_prefixYes

AIProvider

Actions: create, write, delete

FieldTracked
base_urlYes
created_atNo
deletedYes
display_nameYes
enabledYes
iconYes
idYes
nameYes
settingsYes
settings_key_idNo
typeYes
updated_atNo

AIProviderKey

Actions: create, delete

FieldTracked
api_keyYes
api_key_key_idNo
created_atNo
idYes
provider_idYes
updated_atNo

AISeatState

Actions: create

FieldTracked
first_used_atYes
last_event_descriptionYes
last_event_typeYes
last_used_atNo
updated_atNo
user_idYes

APIKey

Actions: login, logout, register, create, write, delete

FieldTracked
allow_listNo
created_atYes
expires_atYes
hashed_secretNo
idNo
ip_addressNo
last_usedYes
lifetime_secondsNo
login_typeNo
scopesNo
token_nameNo
updated_atNo
user_idYes

AuditOAuthConvertState

FieldTracked
created_atYes
expires_atYes
from_login_typeYes
to_login_typeYes
user_idYes

Group

Actions: create, write, delete

FieldTracked
avatar_urlYes
chat_spend_limit_microsYes
display_nameYes
idYes
membersYes
nameYes
organization_idNo
quota_allowanceYes
sourceNo

AuditableGroupAIBudget

Actions: write, delete

FieldTracked
created_atNo
group_idNo
group_nameNo
spend_limitYes
spend_limit_microsNo
updated_atNo

AuditableOrganizationMember

FieldTracked
created_atYes
organization_idNo
rolesYes
updated_atYes
user_idYes
usernameYes

AuditableUserAIBudgetOverride

Actions: write, delete

FieldTracked
created_atNo
group_idYes
group_nameYes
spend_limitYes
spend_limit_microsNo
updated_atNo
user_idNo
usernameNo

Chat

Actions: create, write

FieldTracked
agent_idNo
archivedYes
automation_idYes
build_idNo
client_typeNo
compaction_requested_atNo
context_aggregate_hashNo
context_dirty_resourcesNo
context_dirty_sinceNo
context_errorNo
created_atNo
dynamic_toolsNo
generation_attemptNo
group_aclYes
heartbeat_atNo
history_versionNo
idYes
labelsYes
last_errorNo
last_model_config_idNo
last_read_message_idNo
last_reasoning_effortNo
last_turn_summaryNo
manage_automations_enabledYes
mcp_server_idsYes
modeYes
organization_idNo
owner_idYes
owner_nameNo
owner_usernameNo
parent_chat_idNo
pin_orderYes
plan_modeNo
project_idYes
queue_versionNo
requires_action_deadline_atNo
retry_stateNo
retry_state_versionNo
root_chat_idNo
runner_idNo
snapshot_versionNo
started_atNo
statusNo
summaryNo
summary_generated_atNo
titleYes
title_sourceYes
title_updated_atNo
updated_atNo
user_aclYes
worker_idNo
workspace_idYes

ChatAutomation

Actions: create, write, delete

FieldTracked
created_atNo
created_by_chat_idYes
enabledYes
idYes
kindYes
nameYes
new_chat_model_config_idYes
organization_idYes
owner_idYes
promptYes
queue_generationNo
reasoning_effortYes
schedule_cronYes
schedule_next_run_atNo
schedule_revisionNo
schedule_time_zoneYes
target_chat_idYes
target_modeYes
updated_atNo
webhook_consumed_atYes
webhook_secret_hashYes
webhook_secret_versionYes
webhook_useYes
when_busyYes

ChatInstructionSettings

Actions: write

FieldTracked
idNo
include_default_system_promptYes
include_default_system_prompt_setYes
nameNo
plan_mode_instructionsYes
system_promptYes

ChatModelConfig

Actions: create, write, delete

FieldTracked
ai_provider_idYes
compression_thresholdYes
context_limitYes
created_atNo
created_byYes
deletedYes
deleted_atNo
display_nameYes
enabledYes
group_aclYes
idNo
is_defaultYes
modelYes
optionsYes
organization_idNo
updated_atNo
updated_byYes
user_aclYes

ChatOperationalSettings

Actions: write

FieldTracked
chat_auto_archive_daysYes
chat_debug_retention_daysYes
chat_retention_daysYes
computer_use_providerYes
debug_logging_allow_usersYes
idNo
personal_model_overrides_enabledYes
workspace_ttlYes

ChatProject

Actions: create, write, delete

FieldTracked
created_atNo
descriptionYes
iconYes
idYes
nameYes
organization_idYes
owner_idYes
updated_atNo

CustomRole

FieldTracked
created_atNo
display_nameYes
idNo
is_systemNo
member_permissionsYes
nameYes
org_permissionsYes
organization_idNo
site_permissionsYes
updated_atNo
user_permissionsYes

ExperimentRule

Actions: write

FieldTracked
conditionYes
experimentYes
idNo
modeYes
revisionYes

GitSSHKey

Actions: create

FieldTracked
created_atNo
private_keyYes
private_key_key_idNo
public_keyYes
updated_atNo
user_idYes

GroupSyncSettings

FieldTracked
auto_create_missing_groupsYes
fieldYes
legacy_group_name_mappingNo
mappingYes
regex_filterYes

HealthSettings

FieldTracked
dismissed_healthchecksYes
idNo

License

Actions: create, delete

FieldTracked
expYes
idNo
jwtNo
uploaded_atYes
uuidYes

MCPServerConfig

Actions: create, write, delete

FieldTracked
allow_in_plan_modeYes
api_key_headerYes
api_key_valueYes
api_key_value_key_idNo
auth_typeYes
availabilityYes
created_atNo
created_byYes
custom_headersYes
custom_headers_key_idNo
descriptionYes
display_nameYes
enabledYes
forward_coder_headersYes
group_aclYes
icon_urlYes
idNo
model_intentYes
oauth2_auth_urlYes
oauth2_client_idYes
oauth2_client_secretYes
oauth2_client_secret_key_idNo
oauth2_revocation_urlYes
oauth2_scopesYes
oauth2_token_urlYes
organization_idNo
signing_secretYes
signing_secret_key_idNo
slugYes
tool_allow_listYes
tool_deny_listYes
transportYes
updated_atNo
updated_byYes
urlYes
user_aclYes

NotificationTemplate

FieldTracked
actionsYes
body_templateYes
enabled_by_defaultYes
groupYes
idNo
kindYes
methodYes
nameYes
title_templateYes

NotificationsSettings

FieldTracked
idNo
notifier_pausedYes

OAuth2ProviderApp

FieldTracked
callback_urlYes
client_id_issued_atNo
client_secret_expires_atYes
client_typeYes
client_uriYes
contactsYes
created_atNo
dynamically_registeredYes
grant_typesYes
iconYes
idNo
jwksYes
jwks_uriYes
logo_uriYes
nameYes
policy_uriYes
redirect_urisYes
registration_access_tokenYes
registration_client_uriYes
response_typesYes
scopeYes
software_idYes
software_versionYes
token_endpoint_auth_methodYes
tos_uriYes
updated_atNo

OAuth2ProviderAppSecret

FieldTracked
app_idNo
created_atNo
display_secretNo
hashed_secretNo
idNo
last_used_atNo
secret_prefixNo

OAuth2ProviderSettings

FieldTracked
dynamic_client_registration_enabledYes
idNo

Organization

FieldTracked
created_atNo
default_org_member_rolesYes
deletedYes
descriptionYes
display_nameYes
iconYes
idNo
is_defaultYes
nameYes
shareable_workspace_ownersYes
updated_atYes

OrganizationSyncSettings

FieldTracked
assign_defaultYes
fieldYes
mappingYes

PrebuildsSettings

FieldTracked
idNo
reconciliation_pausedYes

RoleSyncSettings

FieldTracked
fieldYes
mappingYes

Template

Actions: write, delete

FieldTracked
active_version_idYes
activity_bumpYes
agents_allowedYes
allow_user_autostartYes
allow_user_autostopYes
allow_user_cancel_workspace_jobsYes
allow_workspace_renamesYes
autostart_block_days_of_weekYes
autostop_requirement_days_of_weekYes
autostop_requirement_weeksYes
cors_behaviorYes
created_atNo
created_byYes
created_by_avatar_urlNo
created_by_nameNo
created_by_usernameNo
default_ttlYes
deletedNo
deprecatedYes
descriptionYes
disable_module_cacheYes
display_nameYes
failure_ttlYes
group_aclYes
iconYes
idYes
max_port_sharing_levelYes
nameYes
organization_display_nameNo
organization_iconNo
organization_idNo
organization_nameNo
provisionerYes
require_active_versionYes
time_til_autostop_notifyYes
time_til_dormantYes
time_til_dormant_autodeleteYes
updated_atNo
use_classic_parameter_flowYes
user_aclYes

TemplateVersion

Actions: create, write

FieldTracked
archivedYes
created_atNo
created_byYes
created_by_avatar_urlNo
created_by_nameNo
created_by_usernameNo
external_auth_providersNo
has_external_agentNo
idYes
job_idNo
messageNo
nameYes
organization_idNo
readmeYes
source_example_idNo
template_idYes
updated_atNo

User

Actions: create, write, delete

FieldTracked
avatar_urlNo
chat_spend_limit_microsYes
created_atNo
deletedYes
emailYes
github_com_user_idNo
hashed_one_time_passcodeNo
hashed_passwordYes
idYes
is_service_accountYes
is_systemYes
last_seen_atNo
login_typeYes
nameYes
one_time_passcode_expires_atYes
quiet_hours_scheduleYes
rbac_rolesYes
statusYes
updated_atNo
usernameYes

UserSecret

Actions: create, write, delete

FieldTracked
created_atNo
descriptionYes
enabledYes
env_nameYes
file_pathYes
idYes
nameYes
updated_atNo
user_idYes
valueYes
value_key_idNo

UserSkill

Actions: create, write, delete

FieldTracked
contentYes
created_atNo
descriptionYes
idYes
nameYes
updated_atNo
user_idYes

WorkspaceBuild

Actions: start, stop

FieldTracked
build_numberNo
created_atNo
daily_costNo
deadlineNo
has_external_agentNo
idNo
initiator_by_avatar_urlNo
initiator_by_nameNo
initiator_by_usernameNo
initiator_idNo
job_idNo
max_deadlineNo
notified_autostop_deadlineNo
reasonNo
template_version_idYes
template_version_preset_idNo
transitionNo
updated_atNo
workspace_idNo

WorkspaceProxy

FieldTracked
created_atYes
deletedNo
derp_enabledYes
derp_onlyYes
display_nameYes
iconYes
idYes
nameYes
region_idYes
token_hashed_secretYes
updated_atNo
urlYes
versionYes
wildcard_hostnameYes

WorkspaceTable

FieldTracked
automatic_updatesYes
autostart_scheduleYes
created_atNo
deletedNo
deleting_atYes
dormant_atYes
favoriteYes
group_aclYes
idYes
last_used_atNo
nameYes
next_start_atYes
organization_idNo
owner_idYes
template_idYes
ttlYes
updated_atNo
user_aclYes

How to Filter Audit Logs

You can filter audit logs by the following parameters:

  • resource_type - The type of the resource, such as a workspace, template, or user. For more resource types, refer to the CoderSDK package documentation.
  • resource_id - The ID of the resource.
  • resource_target - The name of the resource. Can be used instead of resource_id.
  • action- The action applied to a resource, such as create or delete. For more actions, refer to the CoderSDK package documentation.
  • username - The username of the user who triggered the action. You can also use me as a convenient alias for the logged-in user.
  • email - The email of the user who triggered the action.
  • date_from - The inclusive start date with format YYYY-MM-DD.
  • date_to - The inclusive end date with format YYYY-MM-DD.
  • build_reason - The reason for the workspace build, if resource_type is workspace_build. Refer to the CoderSDK package documentation for a list of valid build reasons.

Capture and export audit logs

In addition to the Coder dashboard, there are multiple ways to consume or query audit trails.

REST API

You can retrieve audit logs via the Coder API.

Visit the get-audit-logs endpoint documentation for details.

Service Logs

Audit trails are also dispatched as service logs and can be captured and categorized using any log management tool such as Splunk.

Example of a JSON formatted audit log entry:

{ "ts": "2023-06-13T03:45:37.294730279Z", "level": "INFO", "msg": "audit_log", "caller": "/home/coder/coder/enterprise/audit/backends/slog.go:38", "func": "github.com/coder/coder/v2/enterprise/audit/backends.(*SlogExporter).ExportStruct", "logger_names": ["coderd"], "fields": { "ID": "033a9ffa-b54d-4c10-8ec3-2aaf9e6d741a", "Time": "2023-06-13T03:45:37.288506Z", "UserID": "6c405053-27e3-484a-9ad7-bcb64e7bfde6", "OrganizationID": "00000000-0000-0000-0000-000000000000", "Ip": null, "UserAgent": null, "ResourceType": "workspace_build", "ResourceID": "ca5647e0-ef50-4202-a246-717e04447380", "ResourceTarget": "", "Action": "start", "Diff": {}, "StatusCode": 200, "AdditionalFields": { "workspace_name": "linux-container", "build_number": "9", "build_reason": "initiator", "workspace_owner": "" }, "RequestID": "bb791ac3-f6ee-4da8-8ec2-f54e87013e93", "ResourceIcon": "" } }

Example of a human readable audit log entry:

2023-06-13 03:43:29.233 [info] coderd: audit_log ID=95f7c392-da3e-480c-a579-8909f145fbe2 Time="2023-06-13T03:43:29.230422Z" UserID=6c405053-27e3-484a-9ad7-bcb64e7bfde6 OrganizationID=00000000-0000-0000-0000-000000000000 Ip=<nil> UserAgent=<nil> ResourceType=workspace_build ResourceID=988ae133-5b73-41e3-a55e-e1e9d3ef0b66 ResourceTarget="" Action=start Diff="{}" StatusCode=200 AdditionalFields="{\"workspace_name\":\"linux-container\",\"build_number\":\"7\",\"build_reason\":\"initiator\",\"workspace_owner\":\"\"}" RequestID=9682b1b5-7b9f-4bf2-9a39-9463f8e41cd6 ResourceIcon=""

Purge old audit logs

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 purging any audit data.

Data Retention

Coder supports configurable retention policies that automatically purge old Audit Logs. To enable automated purging, configure the --audit-logs-retention flag or CODER_AUDIT_LOGS_RETENTION environment variable. For comprehensive configuration options, see Data Retention.

Manual Purging

Alternatively, you can purge Audit Logs manually by running SQL queries directly against the database.

Audit Logs can account for a large amount of disk usage. Use the following query to determine the amount of disk space used by the audit_logs table.

SELECT relname AS table_name, pg_size_pretty(pg_total_relation_size(relid)) AS total_size, pg_size_pretty(pg_relation_size(relid)) AS table_size, pg_size_pretty(pg_indexes_size(relid)) AS indexes_size, (SELECT COUNT(*) FROM audit_logs) AS total_records FROM pg_catalog.pg_statio_user_tables WHERE relname = 'audit_logs' ORDER BY pg_total_relation_size(relid) DESC;

Should you wish to purge these records, it is safe to do so. This can only be done by running SQL queries directly against the audit_logs table in the database. We advise users to only purge old records (>1yr) and in accordance with your compliance requirements.

Maintenance Procedures for the Audit Logs Table

Note

VACUUM FULL acquires an exclusive lock on the table, blocking all reads and writes. For more information, see the PostgreSQL VACUUM documentation.

You may choose to run a VACUUM or VACUUM FULL operation on the audit logs table to reclaim disk space. If you choose to run the FULL operation, consider the following when doing so:

  • Run during a planned maintenance window to ensure ample time for the operation to complete and minimize impact to users

  • Stop all running instances of coderd to prevent connection errors while the table is locked. The actual steps for this will depend on your particular deployment setup. For example, if your coderd deployment is running on Kubernetes:

    kubectl scale deployment coder --replicas=0 -n coder
  • Terminate lingering connections before running the VACUUM operation to ensure it starts immediately

    SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = 'coder' AND pid <> pg_backend_pid();
  • Only coderd needs to scale down - external provisioner daemons, workspace proxies, and workspace agents don't connect to the database directly.

After the vacuum completes, scale coderd back up:

kubectl scale deployment coder --replicas= -n coder

Backup/Archive

Consider exporting or archiving these records before deletion:

-- Export to CSV COPY (SELECT * FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year') TO '/path/to/audit_logs_archive.csv' DELIMITER ',' CSV HEADER; -- Copy to archive table CREATE TABLE audit_logs_archive AS SELECT * FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year';

Permanent Deletion

Note

For large audit_logs tables, consider running the DELETE operation during maintenance windows as it may impact database performance. You can also batch the deletions to reduce lock time.

DELETE FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year'; -- Consider running `VACUUM VERBOSE audit_logs` afterwards for large datasets to reclaim disk space.

How to Enable Audit Logs

This feature is only available with a Premium license, and is automatically enabled.