Skip to content

CONCEPT Cited by 2 sources

Audit trail

An audit trail is a durable, queryable record of every state-changing operation performed against a system — who changed what, when, and to what new value — independent of the system's primary storage. A good audit trail is first-class, not a logs-grep afterthought: it has a defined schema, retention policy, and query API.

Field-level diff as the right granularity

Flagship's audit-trail framing, from the 2026-04-17 launch post:

"A full audit trail. Every flag change is recorded with field-level diffs, so you know who changed what and when."

Field-level diff is the load-bearing shape: not "Alice updated flag X at 14:02" (useless for debugging) but "Alice changed rules[1].conditions[0].value from enterprise to pro at 14:02 UTC". The diff is the answer to the forensic question.

The pattern is positioned against the hardcoded-flag anti- pattern:

"There's no audit trail — when something breaks, you're searching git blame to figure out who toggled what."

git blame is a weak audit trail because it only captures code-embedded toggles — config edits on a dashboard disappear entirely.

What an audit trail is for

Three distinct audiences, each with different query shapes:

  • Incident forensics"what was the last change to the bot-management feature file before the 2025-11-18 outage?" (see [[sources/2025-11-18-cloudflare-outage-on- november-18-2025]] where absence of fine-grained change attribution lengthened the debugging loop.)
  • Compliance"show every time a user's access was modified in the last 12 months, with actor + timestamp + before/after."
  • Operational review"who flipped the flag, and what did they change it from/to — is the new value the one the change ticket asked for?"

Each audience implies different retention policies (months vs. years vs. permanent), different query surfaces (search, SQL, time-range filter), and different PII posture.

Architectural placement

Common implementations, in order of increasing rigour:

  • Logs-only (X updated Y). Cheapest, weakest query surface, lossy.
  • Change-log table in the primary DB. Co-located; risks being corrupted by the same bug that corrupts the primary data.
  • Separate append-only store. Durable, independent of primary-DB corruption; examples:
  • Durable Object- embedded changelog alongside the per-app config (see Flagship — the DO "serves as the source of truth for that app's flag configuration and changelog").
  • Permanently-retained OpenSearch index for token operations (see concepts/audit-trail-in-opensearch — Fly.io's Macaroon auth trail).
  • Separate service with its own auth tier. Highest bar; read paths are auditor-only, primary-DB operators don't have write access.

Caveats not named in the Flagship post

  • Retention window"field-level diffs" is the write shape; the post doesn't name how long they're kept.
  • Query API — dashboard-viewable and diff-renderable, but no disclosed export / API for downstream SIEM integration.
  • PII in context attributes — flag evaluation context can contain user attributes; whether those land in the audit trail (and how) isn't walked through.

Seen in

Last updated · 200 distilled / 1,178 read