How the Vaultwarden Event Logging System Works: Architecture and Event Types

Vaultwarden captures every significant vault action in an event database table using a three-tier architecture (Model, Service, API), with event types organized into numeric ranges (1000–2199) that correspond to users, ciphers, collections, groups, and organizations.

The Vaultwarden event logging system provides comprehensive audit trails for self-hosted password managers. As implemented in the dani-garcia/vaultwarden repository, this subsystem tracks security-relevant actions through a structured database schema and REST API. Understanding the event architecture helps administrators configure retention policies and interpret the numeric event type codes used throughout the system.

Three-Layer Architecture

Model Layer (src/db/models/event.rs)

The Model layer defines the Event struct and the EventType enum, which enumerates every supported audit event. This file contains the database schema mapping, serialization logic, and query methods including Event::clean_events for retention management.

Service Layer (src/api/core/events.rs)

The Service layer implements the core logging helpers _log_user_event and _log_event. These functions construct Event instances, populate foreign-key fields (user_uuid, org_uuid, cipher_uuid, etc.), and persist records via Event::save or Event::save_user_event.

API Layer (src/api/core/events.rs)

The API layer exposes read-only endpoints (/organizations/:id/events, /ciphers/:id/events, /organizations/:org_id/users/:member_id/events) and the /collect endpoint for client-submitted events. These handlers translate query parameters into NaiveDateTime ranges and return paginated JSON responses.

Event Creation and Routing

All logging operations first check CONFIG.org_events_enabled() in src/config.rs. If disabled, the function returns immediately without writing to the database.

User-Centric Events (1000–1099)

User events such as UserLoggedIn (1000) and UserChangedPassword (1001) flow through log_user_event_log_user_event. This creates one global event plus duplicate entries for every organization the user belongs to, ensuring complete audit trails across organizational boundaries.

Organization and Object Events

Events in ranges 1100–2199 route through _log_event, which matches the event_type numeric code to populate specific foreign-key columns:

  • 1100–1199: Cipher operations (stores cipher_uuid)
  • 1300–1399: Collection changes (stores collection_uuid)
  • 1400–1499: Group lifecycle (stores group_uuid)
  • 1500–1599: Organization membership (stores org_user_uuid)
  • 1600–1699: Organization-level actions (no source object required)
  • 1700–1799: Policy updates

Querying Events with Pagination

The API returns pages of 30 events (defined by Event::PAGE_SIZE in src/db/models/event.rs).

When a page contains exactly 30 results, the API generates a continuation token containing the ISO-8601 timestamp of the last event. Clients pass this token as the end parameter to retrieve subsequent pages, enabling efficient chronological traversal of large audit logs.

Event Retention and Cleanup

Vaultwarden automatically purges old events via the event_cleanup_job defined in src/api/core/events.rs. This background task invokes Event::clean_events to delete records older than the number of days specified by CONFIG.events_days_retain(), preventing unbounded database growth.

Complete Reference of Vaultwarden Event Types

The EventType enum in src/db/models/event.rs maps numeric codes to semantic meanings following Bitwarden’s upstream specification:

  • 1000–1099: User actions (UserLoggedIn, UserFailedLogIn, UserClientExportedVault)
  • 1100–1199: Cipher operations (CipherCreated, CipherUpdated, CipherAttachmentCreated, CipherClientCopiedPassword)
  • 1300–1399: Collection management (CollectionCreated, CollectionUpdated)
  • 1400–1499: Group administration (GroupCreated, GroupDeleted)
  • 1500–1599: Membership events (OrganizationUserInvited, OrganizationUserConfirmed, OrganizationUserApprovedAuthRequest)
  • 1600–1699: Organization changes (OrganizationUpdated, OrganizationPurgedVault)
  • 1700–1799: Policy modifications (PolicyUpdated)
  • 1800–2199: Reserved for future provider, domain, and secret retrieval events (currently unimplemented)

Practical Examples

Logging a User Login Event

use vaultwarden::api::events::log_user_event;
use vaultwarden::db::{DbConn, models::UserId};
use std::net::IpAddr;

let conn: DbConn = /* obtain from pool */;
let user_id = UserId::new("c0ffee-dead-beef-1234");
let device_type = 1; // Browser client
let ip: IpAddr = "203.0.113.42".parse().unwrap();

// Creates global event + per-organization copies
log_user_event(1000, &user_id, device_type, &ip, &conn).await;

Submitting Events via the Collect API

curl -X POST https://vault.example.com/collect \
  -H "Content-Type: application/json" \
  -d '[
    {"type": 1100, "date": "2024-03-07T12:34:56Z", "cipher_id": "uuid-here"},
    {"type": 1000, "date": "2024-03-07T12:35:10Z"}
  ]'

Retrieving Organization Events

GET /organizations/123e4567-e89b-12d3-a456-426655440000/events?start=2024-03-01T00:00:00Z&end=2024-03-07T23:59:59Z

Response includes continuationToken for pagination:

{
  "data": [{"type": 1600, "organizationId": "...", "date": "2024-03-06T18:22:10Z"}],
  "object": "list",
  "continuationToken": "2024-03-06T18:22:10Z"
}

Summary

  • Vaultwarden event logging uses a three-layer architecture spanning src/db/models/event.rs (data) and src/api/core/events.rs (service/API)
  • The system creates duplicate user events across all user organizations while maintaining single records for organization-scoped actions
  • Event types are categorized into numeric ranges (1000–2199) covering users, ciphers, collections, groups, and policies
  • Pagination uses continuation tokens based on timestamps with a fixed page size of 30 events
  • Automatic cleanup runs via event_cleanup_job respecting the events_days_retain configuration

Frequently Asked Questions

How do I enable event logging in Vaultwarden?

Set the environment variable ORG_EVENTS_ENABLED=true or configure org_events_enabled in your settings. This flag is checked at runtime by _log_user_event and _log_event; when disabled, all logging calls return immediately without database writes.

What is the difference between user events and organization events?

User events (1000–1099) are replicated across every organization the user belongs to via _log_user_event, ensuring compliance visibility for all admins. Organization events (1600–1699) and object-specific events (1100–1599) create single records scoped to specific organizations via _log_event.

How long does Vaultwarden retain audit events?

Retention is controlled by EVENTS_DAYS_RETAIN (default varies by configuration). The event_cleanup_job periodically executes Event::clean_events to hard-delete records older than this threshold from the event table.

Can I query events for specific ciphers or users?

Yes. The API provides targeted endpoints: /ciphers/:id/events for item-specific history and /organizations/:org_id/users/:member_id/events for per-member audit trails. Both support start and end date parameters with continuation token pagination.

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 →