System Design

Design an Audit Trail

Step 1 / 9

Learn system design by building an audit and compliance trail step by step.

The numbers to beatwho·what·when·whereper eventat the momentnot laterone schemaqueryable

In the interview room

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

Functional requirements

What it must do — agree on these before drawing a single box.

  • Capture: a structured who / what / when / where for every consequential action, at the moment it happens.
  • Append-only: write entries to immutable (WORM) storage — added, never edited or deleted.
  • Prove integrity: hash-chain entries so any edit, deletion or reorder is detectable.
  • Retain: keep for the compliance window, archive to cold storage, then delete when allowed.
  • Query: auditors search by actor, target or time under access control, sensitive fields redacted.

Non-functional requirements

The qualities that shape the whole design — each one names the mechanism that buys it.

Trustworthy, complete facts
A structured event — identity, action, target, timestamp, source — captured at the moment of the action in one consistent schema, never reconstructed from debug logs.
History unrewritable even by admins
Append-only, write-once (WORM) storage: entries can be added but never modified or deleted before retention expires.
Auditing never blocks the app
A durable, ordered append pipeline carries events to the immutable store off the hot path, so no event is lost on a spike.
Prove the trail wasn’t altered
Hash-chain each entry to the previous one and periodically sign the head, so any change breaks the chain and is detectable — proof, not assertion.
Satisfy retention without over-retaining
A per-type retention window with cold archival and deletion past the window (and legal-hold overrides) — over-retaining sensitive data is its own risk.
Reading the trail is itself controlled
A query index behind access control and field redaction, and every read of the trail is an audited action too — the watchers get watched.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

A structured event per actionover reconstructing from debug logs

Debug logs are inconsistent, incomplete and rotated away before the auditor asks, and recording only the action drops the who, when and target. A consistent schema captured at the moment is a fact an auditor can query and trust.

Append-only, immutable storageover admin-only edit permissions

Admins are exactly the people an audit log must hold accountable, so “admins can edit” defeats the purpose. Immutability has to be a property of the store, not a permission — an audit log you can change is not an audit log.

Hash-chaining with a signed headover encrypting the log

Encryption protects confidentiality, not integrity — an attacker who can write can still splice or delete records undetected. Chaining each entry to a hash of the previous makes any change break the chain, turning tampering from prohibited into provable.

Deleting past the retention windowover keeping everything forever

Over-retaining personal data is itself a compliance and privacy risk (data-minimization), while under-retaining fails the rule. Retention cuts both ways: keep at least the required window with legal-hold overrides, then delete.

Auditing the audit accessover unrestricted auditor access

The trail concentrates sensitive who-did-what data, so uncontrolled reads are their own breach. Gate and redact reads, and record every read — reading accountability data is a privileged action too.

What this teaches

Learn system design by building an audit and compliance trail step by step. An interactive guide covering structured capture of who-did-what-when, an append-only immutable store, tamper-evidence with hash chaining, retention and archival for compliance windows, and access-controlled querying that redacts sensitive data — the audit system a forward deployed engineer needs to pass a customer’s security review.

Key takeaways

  • A dedicated audit trail is evidence, not debug output — different guarantees.
  • Capture a structured who/what/when/where on every consequential action, at the moment.
  • Write append-only to immutable (WORM) storage — unrewritable even by admins.
  • Hash-chain entries so any tampering breaks the chain and is provably detectable.
  • Enforce retention: keep long enough for the rule, archive, and delete when allowed.
  • Index for auditors, gate and redact access, and audit the audit access itself.

Concepts covered

  • What is an audit trail?
  • Record what happens
  • Structured who / what / when
  • Append-only + immutable
  • Tamper-evidence
  • Retention + archival
  • Query + access control

Design an Audit Logging & Compliance Trail — read the full walkthrough as text

the same steps, decisions & trade-offs, for reading, reference & search

The big idea

What is an audit trail?

A customer’s security and compliance team needs to answer, at any time: who accessed or changed this, and when? — and to trust the answer completely, even against the people the log is meant to hold accountable. Ordinary application logs aren’t enough: they’re unstructured, incomplete, mutable, and not built to be trusted evidence.

Build a purpose-built trail: capture a structured who/what/when on every action, write it to an append-only immutable store, make it tamper-evident with hash chaining, enforce a retention window, and let auditors query it under access control. It turns "we think it was fine" into provable evidence.

How to read this: We add one piece at a time, problem then fix, and the diagram grows. Hit Begin.

Step 1 · The skeleton

Record what happens

The naive version: the Application writes a line to a log store when something happens. It works until an auditor asks a precise question — and you find the logs are patchy, mutable, and missing the who or the when.

Stand up the Application writing events to a dedicated audit store, separate from ordinary debug logs. Everything that follows makes those events complete, trustworthy, and durable enough to be evidence.

An audit log is evidence, not debug output: Debug logs help you fix bugs; an audit trail proves what happened to a skeptical third party. Different purpose, different guarantees — completeness, immutability, and integrity.

Step 2 · Capture the facts

Structured who / what / when

"User did something" is useless to an auditor. You need the full fact — identity, action, target, timestamp, source — captured consistently on every consequential action, not reconstructed later from scattered logs that may not agree.

Design decision: An auditor asks "who changed this record, and when?" What must every audit event capture?

The call: A structured event: who (identity), what (action + target), when (timestamp), where (source). — Capture each action as a consistent structured record — identity, action, target, timestamp, source, and before/after where relevant — at the moment it happens. That’s a fact an auditor can query and trust.

Add an Audit Capture step that records a structured event for every consequential action — who, what, when, where, and before/after where it matters — the moment it happens, in a consistent schema an auditor can query.

Capture the full fact, consistently: Every entry answers who did what to which target, when, and from where. Consistency across all actions is what lets an auditor query the trail instead of reading prose.

Step 3 · Can’t be changed

Append-only + immutable

If an audit entry can be edited or deleted, the trail is worthless — the very people it holds accountable could rewrite history, and an auditor can’t trust any of it. And writing audit synchronously on the hot path would slow the app.

Design decision: The people an audit log holds accountable could edit it. How do you make the trail trustworthy?

The call: Write to append-only, immutable (write-once) storage — no edits or deletes. — An audit store must be write-once, read-many: entries can be added but never modified or deleted before retention expires. If no one — not even an admin — can change history, the trail becomes trustworthy. Carry events over a durable pipeline so audit never blocks the app.

Write audit events to an append-only, immutable (WORM) store — entries can be added but never edited or deleted before retention expires. Carry them over a durable Append Pipeline so auditing never blocks or slows the application.

Immutability is the foundation: An audit log you can change is not an audit log. Append-only, write-once storage makes history unrewritable — even by admins — which is the whole point. A durable pipeline keeps it off the hot path.

Step 4 · Prove it wasn’t altered

Tamper-evidence

Append-only stops ordinary edits, but a privileged attacker who reaches the storage layer could still splice in, delete, or reorder records. You need to be able to prove the trail is intact, not just assert it.

Design decision: A privileged attacker reaches the storage and alters records. How do you make tampering detectable?

The call: Hash-chain each entry to the previous one (and periodically sign the head). — Each entry includes a hash of the previous entry, forming a chain; any edit, deletion, or reorder changes a hash and breaks the chain, which is detectable. Periodically signing or publishing the chain head anchors it. Tampering becomes provable, not just prohibited.

Make the trail tamper-evident: each entry includes a hash of the previous one, forming a chain, and you periodically sign or publish the chain head. Any edit, deletion, or reorder breaks a hash and is detectable — you can prove the log is intact.

Hash-chaining turns trust into proof: Linking each record to a hash of the last means the whole history is verifiable end to end. Break any link and the chain no longer validates — tampering can’t hide.

Step 5 · Keep it the right length

Retention + archival

Regulations require keeping records for a set period (often years) — but keeping everything hot forever is expensive, and keeping some data too long is itself a compliance and privacy risk. The trail needs a defined lifecycle.

Add Retention: enforce the required window per record type, move older entries to cheap cold/archival storage, and delete once the window (and any legal hold) expires. The trail satisfies the regulation without growing without bound or over-retaining.

Retention is a compliance control both ways: Keep long enough to satisfy the rule, and no longer than allowed. Tiered storage (hot → cold → delete) with legal-hold overrides makes the lifecycle policy, not a guess.

Step 6 · Let auditors in — carefully

Query + access control

Auditors need to search the trail fast — by actor, target, or time — but the audit log itself contains sensitive data, and reading it is a privileged, sensitive action. Uncontrolled access to the audit log is its own breach.

Build a Query Index over the immutable store so auditors search quickly without touching the records, and put it behind Access + Redact: control who may read, redact sensitive fields on read, and — crucially — audit the audit access itself. Reading the trail is a recorded action too.

The audit log is sensitive data: Querying accountability data must itself be controlled and recorded. Index for speed, gate access tightly, redact on read, and log every read — the watchers get watched.

You did it

You just designed an audit & compliance trail.

  • A dedicated audit trail is evidence, not debug output — different guarantees.
  • Capture a structured who/what/when/where on every consequential action, at the moment.
  • Write append-only to immutable (WORM) storage — unrewritable even by admins.
  • Hash-chain entries so any tampering breaks the chain and is provably detectable.
  • Enforce retention: keep long enough for the rule, archive, and delete when allowed.
  • Index for auditors, gate and redact access, and audit the audit access itself.
built to prove who did what, not memorized — capture, append-only, tamper-evident, retain, redact.
Finished this one? 0 / 65 System Designs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More System Designs