Audit logs your auditor will accept

Append-only, timestamped, with subject and object identified. Five specific requirements that most home-grown logs miss.

· LoginWith team

Compliance frameworks (SOC 2, ISO 27001, HIPAA) all want audit logs. What they mean by “audit logs” is more specific than most teams implement. Here’s the checklist to pass audit without remediation.

Requirement 1: Immutability

Audit logs must be write-once. An attacker who gains DB access shouldn’t be able to delete rows that prove the attack happened.

Implementations that pass:

  • Append-only table with DB-level restrictions: revoke UPDATE and DELETE privileges from the application user. Only a separate privileged process can modify the table (and only for retention-policy cleanup).
  • Write-once object store (S3 with object lock): logs are serialized and written as immutable objects, expiring only per retention policy.
  • Dedicated log service (Datadog, Honeycomb, Splunk): the service itself is managed, the logs flow out of your infrastructure.

Implementations that fail:

  • A logs table in your main database with normal read-write access from the app user (if a bad actor compromises the app, they can wipe the evidence).
  • Logs written to a file that the same process rotates or deletes.

Requirement 2: High-resolution UTC timestamps

Every log entry needs a timestamp with millisecond precision, in UTC, from a synchronized clock source. Local time zones cause endless confusion across auditors and investigators.

"timestamp": "2026-04-20T14:32:11.421Z"

Requirement 3: Subject identification

Every action has a subject — the entity performing the action. That’s almost always a user, but can be a service account, an API key, or “system” for automated processes.

"subject": {
  "type": "user",
  "id": "usr_abc123",
  "email": "jane@example.com"
}

Include the email or some human-readable identifier — an auditor reading the log shouldn’t have to run a separate query to know who usr_abc123 is.

Requirement 4: Object identification

For actions on specific resources, identify the object:

"object": {
  "type": "workspace",
  "id": "wks_xyz789",
  "name": "Acme Marketing"
}

“User deleted a workspace” is insufficient without knowing which one.

Requirement 5: Retention

Most frameworks require 7 years of audit log retention. Some require fewer:

  • SOC 2: typically 1 year, up to auditor preference
  • ISO 27001: 3 years typical
  • HIPAA: 6 years
  • PCI-DSS: 1 year
  • GDPR: “as long as necessary” — audit retention of 6-7 years is standard

Set the retention policy explicitly in your storage layer. S3 Object Lock supports this natively. Dedicated log services let you configure retention per stream.

Requirement 6: Queryability (often overlooked)

The log is useless if nobody can search it. Auditors ask: “show me all role changes on workspace X in Q4 2025.” If it takes 3 days to produce the answer, you’ve technically failed the spirit of the requirement.

Provide admins a search UI with filtering by subject, action, time range, and object. Most dedicated log services give you this for free.

What trips teams up

  • Logs stored in the app database with normal permissions (not immutable)
  • Logs without tenant context (can’t filter to “just this customer’s actions”)
  • Logs with missing subject on system events (no way to trace automation)
  • Retention policies nobody actually configured (logs auto-deleted after 30 days)

Audit the audit log before the auditor does.

Want auth that just works?

Get started with LoginWith