Logo Developer Guide

Cache

Three-Layer Cache System#

Trilium implements a sophisticated three-tier caching system to optimize performance and enable offline functionality:

1. Becca (Backend Cache)#

Located at: apps/server/src/becca/

// Becca caches all entities in memory
class Becca {
    notes: Record<string, BNote>
    branches: Record<string, BBranch>
    attributes: Record<string, BAttribute>
    attachments: Record<string, BAttachment>
    // ... other entity collections
}

Responsibilities:

  • Server-side entity cache
  • Maintains complete note tree in memory
  • Handles entity relationships and integrity
  • Provides fast lookups without database queries
  • Manages entity lifecycle (create, update, delete)

Key Files:

  • becca.ts - Main cache instance
  • becca_loader.ts - Loads entities from database
  • becca_service.ts - Cache management operations
  • entities/ - Entity classes (BNote, BBranch, etc.)

2. Froca (Frontend Cache)#

Located at: apps/client/src/services/froca.ts

// Froca is a read-only mirror of backend data
class Froca {
    notes: Record<string, FNote>
    branches: Record<string, FBranch>
    attributes: Record<string, FAttribute>
    // ... other entity collections
}

Responsibilities:

  • Frontend read-only cache
  • Lazy loading of note tree
  • Minimizes API calls
  • Enables fast UI rendering
  • Synchronizes with backend via WebSocket

Loading Strategy:

  • Initial load: root notes and immediate children
  • Lazy load: notes loaded when accessed
  • When note is loaded, all parent and child branches load
  • Deleted entities tracked via missing branches

3. Shaca (Share Cache)#

Located at: apps/server/src/share/

Responsibilities:

  • Optimized cache for shared/published notes
  • Handles public note access without authentication
  • Performance-optimized for high-traffic scenarios
  • Separate from main Becca to isolate concerns

Cache Invalidation#

Server-Side:

  • Entities automatically update cache on save
  • WebSocket broadcasts changes to all clients
  • Synchronization updates trigger cache refresh

Client-Side:

  • WebSocket listeners update Froca
  • Manual reload via froca.loadSubTree(noteId)
  • Full reload on protected session changes

Cache Consistency#

Entity Change Tracking:

// Every entity modification tracked
entity_changes (
    entityName: 'notes',
    entityId: 'note123',
    hash: 'abc...',
    changeId: 'change456',
    utcDateChanged: '2025-11-02...'
)

Sync Protocol:

  1. Client requests changes since last sync
  2. Server returns entity_changes records
  3. Client applies changes to Froca
  4. Client sends local changes to server
  5. Server updates Becca and database