How NocoDB Generates and Accesses Audit Logs: A Technical Deep Dive

NocoDB automatically captures every data-changing operation as structured audit entries using model hooks and the generateAuditV1Payload utility in utils/audit.ts, persists them to the nc_audit_v2 table via the Audit model, and exposes them through the AuditsService REST API layer consumed by the frontend Pinia store.

NocoDB is an open-source Airtable alternative that provides comprehensive audit logging to track all data modifications across your projects. Understanding how NocoDB generates and accesses audit logs enables administrators to monitor changes, ensure compliance, and debug issues with full visibility into who changed what and when.

How NocoDB Generates Audit Logs

Audit log generation in NocoDB follows a structured pipeline that begins at the database model layer and ends with a persisted JSON payload containing complete contextual metadata.

Triggering Events via Model Hooks

NocoDB intercepts data operations through lifecycle hooks defined in the model layer. When operations such as afterInsert, afterUpdate, or afterDelete execute, they trigger the audit logging mechanism. These hooks capture the mutation event along with the request context, user identity, and affected row data.

Building the Audit Payload

The generateAuditV1Payload function in utils/audit.ts constructs a standardized JSON payload adhering to the AuditV1<T> schema. This function aggregates:

  • Request context: user, ip, workspace, base, and model identifiers
  • Row identification: row_id parameters linking the audit to specific records
  • Human-readable details: Objects containing before/after values and operation metadata

Extracting Metadata for Context

To ensure audit logs contain sufficient structural context, utils/audit.ts provides specialized extraction utilities:

  • extractColMetaForAudit: Captures column metadata and data types
  • extractRefColumnIfFound: Identifies reference/foreign key relationships
  • extractViewRelatedProps: Includes view-specific properties when changes occur within specific views

Storing Audit Logs in the Database

Once generated, audit payloads persist through a dedicated model layer designed for high-volume logging operations.

The Audit Model and nc_audit_v2 Table

The Audit model defined in models/Audit.ts handles database persistence. Its static insert method writes records to the nc_audit_v2 table, which stores the complete JSON payload along with indexing fields for efficient querying.

The model also exposes recordAuditList(context, params), a query method supporting filtered retrieval by project, model, operation type, date range, and pagination parameters. This method enables the service layer to fetch audit logs with precise granularity while maintaining performance across large datasets.

Accessing and Retrieving Audit Logs

NocoDB exposes audit data through a layered architecture separating data access, business logic, and presentation concerns.

The AuditsService API Layer

The AuditsService in services/audits.service.ts wraps the Audit.recordAuditList method, applying additional formatting and business logic before exposing data to API controllers. This service layer handles authorization checks and data transformation to ensure clients receive properly structured audit entries.

REST API Endpoints

Clients retrieve audit logs via the standard REST endpoint:


GET /api/v1/db/meta/projects/:projectId/audits

This endpoint accepts query parameters for limit, offset, operation type filtering, and date ranges, returning paginated JSON responses containing the audit entry list and total count.

Frontend Integration with Pinia Store

The NocoDB GUI consumes audit data through the reactive Pinia store located at packages/nc-gui/store/audits.ts. This store manages state for the Audit tab interface, fetching data from the REST API and maintaining reactive state for UI components. The store handles loading states, caching, and real-time updates when new audit entries are created.

Implementation Examples

The following examples demonstrate how to generate audit entries programmatically and retrieve them via API calls.

Generating Audit Entries in Model Hooks

When implementing custom model hooks, use the generateAuditV1Payload utility to create compliant audit records:

import { generateAuditV1Payload } from '~/utils/audit';
import { Audits } from '~/models';

// Example: after a row is updated
async function afterUpdateHook(context: NcContext, model: Model, rowId: string, oldRow, newRow) {
  const payload = await generateAuditV1Payload('UPDATE', {
    context,
    row_id: rowId,
    details: {
      // include only non-system fields that changed
      ...newRow,
    },
    // optional: pass the HTTP request if you have it
    req: context?.req,
  });

  // Persist the audit record
  await Audits.insert(payload);
}

Fetching Audit Logs via REST API

To retrieve audit logs from client applications or external integrations:

// Using fetch from the front-end
const projectId = '12345';
const response = await fetch(
  `/api/v1/db/meta/projects/${projectId}/audits?limit=50&offset=0`,
  {
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
  }
);
const { list, count } = await response.json(); // list = array of audit entries

Using the Vue Store in NC-GUI

For frontend development within the NocoDB ecosystem, leverage the existing Pinia store:

import { useAuditsStore } from '@/store/audits';

const auditsStore = useAuditsStore();
await auditsStore.fetchAudits({ projectId: '12345', limit: 100 });
console.log(auditsStore.audits); // Reactive list shown in the Audit tab

Summary

  • Audit generation occurs through model hooks (afterInsert, afterUpdate, afterDelete) that invoke generateAuditV1Payload in utils/audit.ts to create structured AuditV1<T> schema payloads.
  • Metadata enrichment happens via helper functions including extractColMetaForAudit and extractRefColumnIfFound to capture column and relationship context.
  • Persistence flows through the Audit model in models/Audit.ts, which writes to the nc_audit_v2 table and provides the recordAuditList query method.
  • API access is managed by AuditsService in services/audits.service.ts, exposing the GET /api/v1/db/meta/projects/:projectId/audits endpoint with full filtering and pagination support.
  • Frontend consumption utilizes the Pinia store at packages/nc-gui/store/audits.ts to provide reactive audit data to the user interface.

Frequently Asked Questions

What database operations trigger audit logs in NocoDB?

NocoDB generates audit logs for all data-changing operations including insertions, updates, deletions, bulk actions, and link/unlink operations between records. These triggers activate through model lifecycle hooks that capture the operation type, user context, and row modifications automatically.

How are audit logs structured in the NocoDB database?

Audit logs follow the AuditV1<T> JSON schema stored in the nc_audit_v2 table. Each record contains request metadata (user ID, IP address, workspace), model references, row identifiers, and a detailed changes object. The schema supports extensible metadata through functions like extractColMetaForAudit that append column definitions and view properties.

Can I query audit logs programmatically via the NocoDB API?

Yes, the REST API endpoint GET /api/v1/db/meta/projects/:projectId/audits provides programmatic access to audit logs with support for filtering by operation type, date ranges, and pagination parameters. The endpoint returns a JSON object containing a list array of audit entries and a count integer for total records matching your criteria.

Where are audit logs displayed in the NocoDB user interface?

Audit logs are displayed in the dedicated Audit tab within the NocoDB interface. This tab consumes data through the Pinia store defined in packages/nc-gui/store/audits.ts, which fetches records from the backend API and presents them in a searchable, paginated table showing operation history, user details, and change summaries.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →