Audit Trail



An audit trail is a tool used to observe the actions performed in a system. In the case of WorkOS Audit Trail, the system in question is your application.

Application-level audit trail are a useful way to understand your users's activity. This is because audit trails allow you to answer the questions:

  • What specific user actions were performed?
  • Who performed these actions?
  • When were they performed? At what frequency?
  • What target resources have been changed as a result of these user actions? In what ways?

Audit trails allow you to provide definitive answers the question: "Who did what, and when did they do it?"

Unpacking the audit trail

"A tool used to observe the actions performed in a system" is pretty general. So, let's unpack that statement with a bit more detail.

In implementation, an audit trail is an immutable, append-only sequence of events ordered by time. Which begs the question: What is an "event?"

An event is a structured record that contains the contextual information about an action.

To break that definition down: events can be structured in a variety of ways, almost all of which equate to key-value stores. These methods include positional fields, key=val, key:val, etc. In the case of WorkOS Audit Trail, events are structured using JSON.

And regarding the "contextual information" of an event: this includes all of the data relevant to the action being performed. Data such as the actor, the organization or group the actor is a member of, the type of action they're performing, as well as the target of the action, and details about any changed state during the action, are all data you should consider including. Using a user's successful 2-factor authentication confirmation as an example, your event would include:


  "id": "evt_01DGZ0ENR572V8RS7GJ14NWQ08",
  "group": "",
  "location": "",
  "action": "user.2fa_succeeded",
  "action_type": "r",
  "actor_name": "Rosella Lang",
  "actor_id": "user_01DGZ0ENJE08S5QGSE7RAFY9X4",
  "target_name": "[email protected]",
  "target_id": "user_01DGZ0ENJE08S5QGSE7RAFY9X4",
  "metadata": {
    "description": "User 2fa succeeded",
    "x_request_id": "fc695b1b-6fda-4cdb-bd1d-b7d554b8ee22"
  "occurred_at": "2020-08-14T05:04:17.957Z"

Of course, there's a balance to reach. It's understandable that all of the data can't be included for every event all the time. For example, we wouldn't normally expect the entire "before and after" states of an updated document to be included in an audit trail event. That's because maintaining duplicate, detailed copies of those data is not usually in the interest of the people using your application...But sometimes it is! User needs can vary! But, no matter their needs, audit trails can accomodate them.