* Remove outdated documentation files: Quick Start Guide, Apache AGE Analysis, and Scratchpad. * Add multi-tenant testing strategy and ADR index documentation - Introduced ADR 008 detailing the multi-tenant testing strategy for the ./starter environment, covering compatibility and multi-tenant modes, testing scenarios, and implementation details. - Created a comprehensive ADR index (README.md) summarizing all architecture decision records related to the multi-tenant implementation, including purpose, key sections, and reading paths for different roles. * feat(docs): Add comprehensive multi-tenancy guide and README for LightRAG Enterprise - Introduced `0008-multi-tenancy.md` detailing multi-tenancy architecture, key concepts, roles, permissions, configuration, and API endpoints. - Created `README.md` as the main documentation index, outlining features, quick start, system overview, and deployment options. - Documented the LightRAG architecture, storage backends, LLM integrations, and query modes. - Established a task log (`2025-01-21-lightrag-documentation-log.md`) summarizing documentation creation actions, decisions, and insights.
8.3 KiB
8.3 KiB
Multi-Tenant UX & State Management
This document describes the multi-tenant state management architecture implemented in LightRAG, covering tenant switching, URL handling, state persistence, and security considerations.
Overview
LightRAG implements a header-based multi-tenant architecture where:
- Tenant context is provided via
X-Tenant-IDandX-KB-IDHTTP headers - URLs are tenant-agnostic - they contain only UI state (page, filters, sort)
- State is persisted per-tenant in sessionStorage for quick restores
- Security is enforced server-side with token validation
Architecture Diagram
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (WebUI) │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ TenantStateManager │←→│ sessionStorage │ │ URL │ │
│ │ │ │ (tenant-scoped) │ │ (no tenant) │ │
│ └────────┬──────────┘ └─────────────────┘ └──────────────┘ │
│ │ │
│ ┌────────▼──────────┐ │
│ │ Axios Interceptor │ ──── Adds X-Tenant-ID / X-KB-ID headers │
│ └────────┬──────────┘ │
└───────────┼─────────────────────────────────────────────────────┘
│
▼ HTTP Requests with headers
┌───────────────────────────────────────────────────────────────────┐
│ Backend (API) │
├───────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────┐ │
│ │ dependencies.py │ ─── Extracts & validates tenant context │
│ │ get_tenant_context │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌──────────▼──────────┐ ┌─────────────────┐ │
│ │ TenantRAGManager │───→│ Tenant-scoped │ │
│ │ │ │ LightRAG inst. │ │
│ └──────────────────────┘ └─────────────────┘ │
└───────────────────────────────────────────────────────────────────┘
Frontend State Management
TenantStateManager
The tenantStateManager is a centralized module for managing tenant+route state:
import { tenantStateManager } from '@/services/tenantStateManager'
// Get state for current tenant and route
const state = tenantStateManager.getState(tenantId, 'documents')
// Update state (persists to sessionStorage)
tenantStateManager.setState(tenantId, 'documents', { page: 5 })
// Sync to URL (debounced, tenant-agnostic)
tenantStateManager.syncToURL('documents', state)
// Handle tenant switch
tenantStateManager.onTenantSwitch(oldTenantId, newTenantId)
State Storage Strategy
| Priority | Storage | Purpose |
|---|---|---|
| Primary | URL query params | Route-level UI settings (page, filters, sort) |
| Secondary | sessionStorage | Per-tenant state for quick restores |
| Tertiary | In-memory | Fast runtime access |
Key Format for sessionStorage:
lightrag:tenant:<tenantId>:route:<routeName>
useRouteState Hook
React hook for easy integration:
function DocumentManager() {
const {
page,
pageSize,
sort,
sortDirection,
filters,
setPage,
setFilters,
resetState,
} = useRouteState('documents')
// State changes automatically sync to URL and sessionStorage
}
URL Format
URLs are tenant-agnostic for security. Examples:
/documents?kb=backup&page=3&pageSize=25&filters=status:active
/graph?kb=master&view=graph&filters=entityType:company
/retrieval?q=search+query
Security Note: Tenant identifiers are NEVER included in URLs. Tenant context comes from:
X-Tenant-IDheader (required)X-KB-IDheader (optional, defaults to first KB)- Authorization token claims (for validation)
Backend Tenant Resolution
The backend resolves tenant context in dependencies.py:
async def get_tenant_context(
request: Request,
authorization: Optional[str] = Header(None),
x_tenant_id: Optional[str] = Header(None, alias="X-Tenant-ID"),
x_kb_id: Optional[str] = Header(None, alias="X-KB-ID"),
) -> TenantContext:
"""
Priority for tenant_id resolution:
1. Middleware state (subdomain/JWT extracted early)
2. Token metadata
3. X-Tenant-ID header (fallback)
"""
Ingestion Idempotency
The ingestion API supports idempotency via external_id:
# Request
POST /documents/text
X-Tenant-ID: tenant-123
X-KB-ID: kb-456
{
"text": "Document content...",
"external_id": "my-unique-doc-id"
}
# Response (first time)
{"status": "success", "track_id": "insert_xxx"}
# Response (same external_id again)
{"status": "duplicated", "message": "Document with external_id 'my-unique-doc-id' already exists"}
Database Indexes
For optimal performance, the following indexes are created:
-- Pagination indexes
CREATE INDEX idx_doc_status_workspace_status_updated_at
ON LIGHTRAG_DOC_STATUS (workspace, status, updated_at DESC);
CREATE INDEX idx_doc_status_workspace_status_created_at
ON LIGHTRAG_DOC_STATUS (workspace, status, created_at DESC);
-- Idempotency index
CREATE INDEX idx_doc_status_workspace_external_id
ON LIGHTRAG_DOC_STATUS (workspace, (metadata->>'external_id'))
WHERE metadata->>'external_id' IS NOT NULL;
Security Considerations
- Never expose tenant IDs in URLs - Use headers only
- Server-side validation - Always validate tenant context from token
- Tenant isolation - Each tenant's data is stored with workspace prefix
- Strict mode - Set
LIGHTRAG_MULTI_TENANT_STRICT=trueto require tenant context
Testing
Unit Tests
# Frontend tests
cd lightrag_webui
npm run test -- src/__tests__/tenantStateManager.test.ts
# Backend tests
pytest tests/test_idempotency.py -v
E2E Tests
# Requires running server
RUN_E2E_TESTS=1 pytest tests/e2e_multi_tenant_state.py -v
Rollout Checklist
- Deploy backend with new indexes
- Enable
LIGHTRAG_MULTI_TENANT_STRICTin staging - Run e2e tests against staging
- Deploy frontend with tenantStateManager
- Monitor per-tenant request latency
- Monitor ingestion failure rates
Related Documentation
- 0001-multi-tenant-architecture.md - Core architecture
- 0002-multi-tenant-visual-reference.md - Visual diagrams
- LOCAL_DEVELOPMENT.md - Local testing setup