Learning lens
Start with judgment, not a universal prescription.
This page is a learning model for understanding the capability. It does not claim exact production internals, exact costs, or an infinite-scale architecture.
Evidence
Conceptual pattern
0->1 default
Start with explicit trust boundaries, auditable decisions, and managed primitives where correctness matters more than novelty.
Cost drivers
Watch for breakpoints
- -authorization logic spreads across services
- -audit queries become operationally important
- -customers require stronger controls
Learn first
Concepts behind this architecture
Eventual Consistency
Allow replicas to temporarily disagree while guaranteeing they converge later.
Observability
Understand what a production system is doing from its external signals.
Replication
Copy data across nodes to improve availability, read scale, and disaster recovery.
Strong Consistency
Make reads reflect the latest committed write for correctness-critical data.
The Problem
Regulated industries (healthcare, finance, government) and security-conscious applications need a complete, tamper-proof record of who did what, when, and from where. Audit logs answer questions like “Who accessed this patient record?”, “Who changed the billing amount?”, and “What admin actions were taken during the incident?” Unlike application logs (for debugging), audit logs are legal records that may be subpoenaed. They must be immutable, complete, queryable, and retained for years — while adding minimal latency to the operations being audited.
Architectural Approaches
Application-Level Audit Middleware
Intercept operations at the application layer and emit structured audit events. Middleware on API routes captures the actor, action, resource, and outcome. Events are written to a dedicated audit log store asynchronously to avoid impacting request latency.
Pros
- +Rich context — captures business-level semantics (not just SQL)
- +Can include request context (IP, user agent, session)
- +Flexible — audit only what matters, skip noisy operations
- +Works with any database and framework
Cons
- −Must be added to every relevant code path — easy to miss
- −Application bugs can cause missing or incorrect audit entries
- −Developers must remember to add audit logging to new features
- −Bypassed by direct database access
Database-Level Audit Triggers
Use database triggers or change data capture (CDC) to automatically record every INSERT, UPDATE, and DELETE in an audit table. Captures all changes regardless of which application or user made them.
Pros
- +Captures ALL data changes — nothing can be missed
- +Cannot be bypassed by application code
- +Automatic — no developer action needed for new tables
- +Includes before/after values for every change
Cons
- −No application context (who initiated the change, from which UI)
- −High volume — every row change generates an audit entry
- −Performance impact on write-heavy tables
- −Database-specific implementation (Postgres triggers differ from MySQL)
Event Sourcing as Audit Log
If your system uses event sourcing, the event store IS the audit log. Every state change is recorded as an immutable event. The current state is derived by replaying events. The complete history is preserved by design.
Pros
- +Audit logging is built into the architecture — not an afterthought
- +Complete history with perfect fidelity
- +Can reconstruct state at any point in time
- +Events are immutable by design
Cons
- −Event sourcing is a major architectural commitment
- −Not practical to retrofit into existing CRUD applications
- −Event store can grow very large over time
- −Querying historical state requires event replay or projections
Architecture
Key Components
Audit Middleware
Intercepts API requests and emits structured audit events. Captures: actor (user ID, IP, session), action (HTTP method, business operation), resource (type, ID), outcome (success/failure, status code), and timestamp. Emits events asynchronously to avoid blocking the request.
Audit Processor
Consumes audit events from the queue, enriches them with additional context (actor name, resource details), validates the event schema, and writes to the audit store. Handles deduplication and ordering. Runs as a separate service for isolation.
Integrity Signer
Generates a cryptographic hash chain for tamper detection. Each audit entry includes a hash of itself plus the previous entry’s hash, forming an append-only chain. Any modification to a historical entry breaks the chain. Similar to a simplified blockchain.
Hot Audit Store
Queryable database for recent audit logs (last 90 days). PostgreSQL with proper indexing (actor, resource, timestamp) or Elasticsearch for full-text search across audit entries. Optimized for fast queries and filtering.
Cold Archive
Long-term storage for audit logs beyond the hot window. S3 with lifecycle policies moving to Glacier/Deep Archive after 1 year. Stored as compressed, encrypted Parquet or JSON files. Retention period set by compliance requirements (7 years for SOX, 6 years for HIPAA).
Audit Query API & Dashboard
Provides filtered, paginated access to audit logs. Supports queries by actor, resource, action, time range, and outcome. Dashboard for security teams to investigate incidents. Export functionality for compliance auditors (CSV, PDF reports).
Data Model
Tamper-Proof Hash Chain
Audit logs must be tamper-proof — if someone modifies a historical entry, it should be detectable.
Hash chain implementation:
- For each audit event, compute:
hash = SHA-256(event_id + actor + action + resource + timestamp + previous_hash) - Store the hash alongside the event
- The first event in the chain uses a known seed value for previous_hash
- To verify integrity: recompute hashes from the beginning and compare with stored hashes
Verification: Run a daily integrity check job that walks the entire chain and verifies each hash. Any break in the chain indicates tampering. Alert the security team immediately.
Anchoring: Periodically publish the latest hash to an external system (a public blockchain, a separate write-once storage, or a third-party timestamping service). This prevents an attacker who gains database access from rewriting the entire chain.
Performance: SHA-256 hashing is fast (~1 microsecond per entry). The chain verification job processes millions of entries per minute. Run incrementally — only verify entries since the last check.
Alternative: Use a Merkle tree instead of a linear chain. Allows efficient proof that a specific entry exists in the log without verifying the entire chain. More complex but better for selective verification.
What to Audit
Not every operation needs auditing. Focus on security-relevant and compliance-required events.
Always audit:
- Authentication events: login, logout, failed login attempts, password changes, MFA enrollment
- Authorization changes: role assignments, permission grants/revocations
- Data access: reads of sensitive data (PII, financial records, health data)
- Data modifications: creates, updates, deletes of business-critical records
- Administrative actions: user management, configuration changes, feature flag toggles
- API key and token management: creation, rotation, revocation
Consider auditing:
- Search queries on sensitive data (who searched for patient records?)
- Export operations (who downloaded the customer list?)
- Impersonation/admin access (admin viewed user’s account)
- Billing and payment operations
Skip (use application logs instead):
- Read-only access to non-sensitive data
- Health checks and monitoring requests
- Static asset requests
- Internal service-to-service communication (unless accessing sensitive data)
Structured format: Every audit entry should include: WHO (actor ID, actor type, IP, session), WHAT (action, resource type, resource ID), WHEN (timestamp, timezone), WHERE (IP, user agent, geolocation), and OUTCOME (success/failure, error details).
Retention and Compliance
Different regulations have different retention requirements:
- SOX (Sarbanes-Oxley): 7 years for financial audit trails
- HIPAA: 6 years for access logs to protected health information
- GDPR: Retain only as long as necessary (conflict with long retention!)
- PCI DSS: 1 year minimum, 3 months immediately accessible
- SOC 2: No specific retention, but auditors expect 12+ months
GDPR tension: GDPR requires data minimization — don’t keep data longer than necessary. But audit logs may contain PII (user names, emails, IP addresses). Solutions:
- Anonymize/pseudonymize PII in audit logs after the active period
- Keep audit logs but redact PII fields after the retention window
- Document the legal basis for retaining audit logs (legitimate interest, legal obligation)
Tiered storage:
- Hot (0-90 days): Fast queryable store (PostgreSQL, Elasticsearch). Full detail.
- Warm (90 days - 1 year): Compressed storage (S3 Standard). Queryable with some delay.
- Cold (1-7+ years): Archive storage (S3 Glacier). Retrieved on demand for audits.
Immutability enforcement: Use write-once storage (S3 Object Lock, WORM-compliant storage) for cold archives. Even database administrators cannot modify or delete archived audit logs. This is required for SOX compliance.
Real-World Examples
GitHub
Enterprise audit log capturing all organization-level actions: repository access, member management, SSO events, and API access. Streamable to external SIEM systems via audit log streaming. Searchable via API with filters for actor, action, and time range.
AWS CloudTrail
Records every API call made in an AWS account. Captures who (IAM principal), what (API action), which resource, and when. Logs stored in S3 with optional CloudWatch integration. Supports multi-region and organization-wide trails.
Datadog
Audit Trail feature tracks all configuration changes, user actions, and API access within the Datadog platform. Every dashboard edit, monitor change, and access key creation is logged with full actor context. 90-day retention with export capability.
Stripe
Complete audit trail of all API requests and dashboard actions. Every payment, refund, and configuration change is logged with the actor (API key or dashboard user), timestamp, and request details. Accessible via the dashboard and Events API.
Architectural Tradeoffs
Application-level vs database-level auditing
Pros
- +Application: rich business context, selective auditing
- +Database: captures ALL changes, cannot be bypassed
- +Both: belt-and-suspenders approach for critical systems
Cons
- −Application: can miss changes from direct DB access or other apps
- −Database: noisy, no business context, high volume
- −Both: more complexity, potential duplicate entries
Synchronous vs asynchronous audit logging
Pros
- +Synchronous: guaranteed — if the operation succeeds, the audit entry exists
- +Asynchronous: no latency impact on the operation
- +Asynchronous: can batch writes for better throughput
Cons
- −Synchronous: adds latency to every audited operation
- −Asynchronous: small window where operation succeeds but audit entry is lost
- −Asynchronous: must handle queue failures and ensure delivery
Relational DB vs append-only log (Kafka) for audit storage
Pros
- +Relational: easy querying with SQL, familiar tooling
- +Kafka: naturally append-only, immutable, high throughput
- +Relational: better for complex queries (joins, aggregations)
Cons
- −Relational: rows can be updated/deleted (must restrict access)
- −Kafka: harder to query (need to materialize into a queryable store)
- −Kafka: retention management is partition-based, less granular
Learn Audit Logging
Copy a learning context prompt for an AI assistant. It keeps assumptions visible and asks for tradeoffs, cost drivers, failure modes, and what to measure before adding complexity.
Explore More Capabilities
API Versioning
Backward-compatible API evolution with URL, header, and content negotiation strategies
Caching Strategies
Cache-aside, write-through, invalidation patterns, and distributed caching with Redis
CDN & Asset Delivery
Origin shielding, cache hierarchies, purging strategies, and global content distribution