Audit Logging

An immutable ledger of who did what, when, and where.

The idea

Application logs (`logger.info("request started")`) are for debugging. Audit Logs are for security and compliance. They answer specific questions during an incident: "Who deleted the production database?", "When was this permission granted?", or "Did Alice view Bob's medical records?". Because of this, they must be structured, immutable, and heavily protected.

Step 1: Admin clicks "Delete User".

How it works

Audit events must capture the "Five W's": Who, What, When, Where, and Why (if applicable). They are often written to an append-only datastore (like AWS S3 with Object Lock or a specialized SIEM) so that even if the main database is compromised, the hacker cannot erase their tracks.

def delete_user(admin_id, target_user_id, ip_address):
    # 1. Perform the action
    db.users.delete(target_user_id)
    
    # 2. Fire-and-forget the Audit Log (Async or via Message Queue)
    audit_event = {
        "timestamp": "2023-10-25T14:32:00Z",
        "actor_id": admin_id,
        "action": "user.deleted",
        "target_resource": f"user/{target_user_id}",
        "ip_address": ip_address,
        "status": "success"
    }
    
    # Push to an immutable, append-only store
    audit_queue.publish(audit_event)

Cost

Audit logging increases storage costs (as logs are kept for years for compliance) and adds slight complexity to state-mutating code. It usually requires a dedicated pipeline (like Kafka -> S3) separate from normal application logs.

Watch out for