Skip to content

Architecture

Tom Laird-McConnell edited this page May 24, 2026 · 2 revisions

Architecture: Catalogs and Databases

LottaDB uses a two-level hierarchy:

  • Catalog (LottaCatalog) -- a grouping that maps to one Azure Table and one blob container. Owns shared infrastructure: storage clients, analyzer, embedding generator.
  • Database (LottaDB) -- an isolated partition within a catalog, with its own type registrations.
Catalog ("userX")          <- one Azure Table "userX", one blob container "/userX"
+-- Database "notes"            <- PartitionKey="notes", Lucene index at userX/notes
|   +-- Store<Note>()
|   +-- On<Note>(handler)
+-- Database "todos"            <- PartitionKey="todos", Lucene index at userX/todos
|   +-- Store<Todo>()
+-- Database "settings"         <- PartitionKey="settings", Lucene index at userX/settings
    +-- Store<UserPrefs>()

Multiple databases in a catalog share a table but are fully isolated -- data in one database is invisible to another.

Multi-Tenancy

Each tenant gets their own catalog. Multiple databases within a catalog provide logical separation for different data types or use cases.

// Per-tenant catalog
var catalog = new LottaCatalog(tenantId, connectionString);

// Separate databases for different concerns
var notesDb = await catalog.GetDatabaseAsync("notes", c => c.Store<Note>());
var todosDb = await catalog.GetDatabaseAsync("todos", c => c.Store<Todo>());

// Tenant leaves -- drop all databases for the tenant
await catalog.DeleteAsync();

Listing and managing databases

// Discover all databases in a catalog
var databases = await catalog.ListAsync();
// ["notes", "todos", "settings"]

// Delete a single database (other databases unaffected)
await notesDb.DeleteDatabaseAsync();

LottaCatalog Operations

Operation Description
GetDatabaseAsync() Get or create a database within the catalog
ListAsync() List all database IDs in the catalog
DeleteAsync() Delete the entire catalog (all databases)
Dispose() Dispose all managed database instances

Catalog-level settings

Infrastructure settings live on the catalog and are shared across all databases. Storage is configured via Use*() extension methods, and other settings are configured via the constructor's configure callback:

// Connection string constructor -- Azure storage is configured automatically
var catalog = new LottaCatalog("myapp", connectionString);

// Or use Use*() methods to pick a provider explicitly
var catalog = new LottaCatalog("myapp", catalog => catalog.UseAzure(connectionString));
var catalog = new LottaCatalog("myapp", catalog => catalog.UseMemory());
var catalog = new LottaCatalog("myapp", catalog => catalog.UseFileSystem(@"C:\data"));
var catalog = new LottaCatalog("myapp", catalog => catalog.UseSQLite(@"C:\data"));

// Combine a provider with other catalog settings
var catalog = new LottaCatalog("myapp", catalog =>
{
    catalog.UseAzure(connectionString);
    catalog.Analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48);
    catalog.EmbeddingGenerator = myEmbeddingGenerator;
});

Each Use*() method configures all three storage concerns (table client, blob client, and Lucene directory) in one call. See Configuration for details on each provider.

Setting Description Default
Analyzer Lucene analyzer for text analysis EnglishAnalyzer
EmbeddingGenerator Embedding generator for vector search null (disabled)

These properties are internal and can only be set through the constructor's configure callback -- not after construction.

Clone this wiki locally