Skip to content

Storage Architecture

Storage Interface

All storage operations go through the IEventStore interface defined in @agentlensai/core. This makes the storage backend pluggable — SQLite and PostgreSQL share the same contract.

typescript
interface IEventStore {
  // Write
  insertEvents(events: AgentLensEvent[]): Promise<void>;
  upsertSession(session: Partial<Session>): Promise<void>;
  upsertAgent(agent: Agent): Promise<void>;

  // Read — Events
  queryEvents(query: EventQuery): Promise<EventQueryResult>;
  getEvent(id: string): Promise<AgentLensEvent | null>;
  getSessionTimeline(sessionId: string): Promise<AgentLensEvent[]>;
  countEvents(query: EventQuery): Promise<number>;

  // Read — Sessions
  querySessions(query: SessionQuery): Promise<SessionQueryResult>;
  getSession(id: string): Promise<Session | null>;

  // Read — Agents
  listAgents(): Promise<Agent[]>;
  getAgent(id: string): Promise<Agent | null>;

  // Analytics
  getAnalytics(params: AnalyticsParams): Promise<AnalyticsResult>;

  // Alert Rules
  createAlertRule(rule: AlertRule): Promise<void>;
  updateAlertRule(id: string, updates: Partial<AlertRule>): Promise<void>;
  deleteAlertRule(id: string): Promise<void>;
  listAlertRules(): Promise<AlertRule[]>;
  getAlertRule(id: string): Promise<AlertRule | null>;

  // Maintenance
  applyRetention(maxAgeDays: number): Promise<{ deletedCount: number }>;
  getStats(): Promise<StorageStats>;
}

SQLite (Default)

Why SQLite?

  • Zero external dependencies — just a file on disk
  • WAL mode enables concurrent reads with writes
  • Excellent performance for single-instance deployments
  • Perfect for self-hosted and edge deployments

Configuration

PragmaValuePurpose
journal_modeWALConcurrent read/write
synchronousNORMALBalance durability + speed
cache_size-6400064 MB page cache
busy_timeout50005s retry on contention

Schema

Managed by Drizzle ORM with automatic migrations on startup.

Tables: events, sessions, agents, alert_rules, alert_history, api_keys, config_kv

Key Indexes:

  • idx_events_timestamp — Time-range queries
  • idx_events_session_id — Session timeline
  • idx_events_agent_id — Agent filtering
  • idx_events_type — Event type filtering
  • idx_events_session_ts — Composite: session + timestamp
  • idx_events_agent_type_ts — Composite: agent + type + timestamp (dashboard pattern)
  • idx_sessions_agent_id, idx_sessions_started_at, idx_sessions_status

PostgreSQL (Team)

For teams needing shared access, configure with:

bash
DATABASE_URL=postgresql://user:pass@host:5432/agentlens
DB_DIALECT=postgresql

Same IEventStore interface, same API behavior.

Retention Policy

A configurable retention engine deletes old events to prevent unbounded growth:

  • Default: 90 days
  • Configurable: RETENTION_DAYS environment variable or Settings page
  • 0 = keep forever
  • Sessions with no remaining events are also cleaned up
  • Runs daily on a scheduled interval

This is the only exception to the "no DELETE" rule — retention cleanup is an audited operation.

Performance Targets

MetricTarget
Event ingestion throughput≥ 1,000 events/sec
Ingestion latency (P95)< 5ms per event (batch of 100)
Query latency (P95)< 100ms for filtered queries (< 1M events)
Timeline render< 1s for sessions with 1,000 events

Released under the MIT License.