Skip to main content
Accountability means every significant action in your system can be traced back to who did it, when, and from where. This page builds a complete logging stack: Morgan for HTTP request logs, a MySQL audit_logs table using db.query(), and Winston for structured application logs.

What Is Accountability

Accountability ensures the system can answer: who did what, when, from where, and with what result?

Who

User ID and role from the JWT (req.user.id)

What

Action: CREATE, UPDATE, DELETE, LOGIN

When

Exact timestamp recorded in the DB

Where

Client IP address and browser user-agent

On What

Resource type (users, posts) and specific ID

Result

SUCCESS or FAILURE based on HTTP status code
Non-repudiation: Users cannot deny performing an action when audit logs with timestamps exist.

MySQL audit_logs Table

Audit Log Service

Using Audit Logs in Routes

Call createAuditLog() after the DB operation inside the callback:

Morgan: HTTP Request Logging

Morgan output example (dev format):

Winston: Application Logging

Usage:

Log Levels

What NOT to Log

Never log these — log files can be stored indefinitely and exposed to monitoring tools:
  • Passwords (plaintext or hashed)
  • JWT tokens
  • Credit card numbers
  • API keys and secrets
  • Social security numbers

Querying Audit Logs

Key Terms

Common Mistakes

Always call sanitizeBody() before passing request body to createAuditLog(). Logging passwords is a GDPR violation.
Audit log failures should be caught and printed to console only. Never let a failed INSERT into audit_logs break the API response.
Without indexes on user_id, action, and created_at, queries over a large audit_logs table take seconds. Always define indexes.