Skip to content

Vector Database

Amplify uses Orama v3 (@orama/orama ^3.1.2) as its vector store engine. Orama provides BM25 full-text search with English stemming and stop-word removal — not embedding-based search. This means deterministic, reproducible results without requiring an embedding model.

Orama BM25 vector store system

Amplify has two separate vector stores that persist context and memory across sessions:

  1. UserProfileVectorStore : User preferences, tech stack, coding style
  2. ProjectContextVectorStore : Per-project decisions, errors, patterns, requirements

Both stores use BM25 (keyword frequency + TF-IDF variant) for search, which is:

  • Deterministic : Same query always returns same results
  • Lightweight : ~2KB gzipped bundle size
  • Browser-native : Runs entirely in IndexedDB, no WASM needed
  • Fast : No embedding model calls, results in milliseconds
BM25 vs Embedding search
AspectBM25 (Orama)Embedding Search
AlgorithmKeyword frequency + TF-IDFCosine similarity of dense vectors
Requires modelNoYes (additional API call)
DeterministicYesNo (depends on embedding model)
Bundle size~2KB~200KB+ (WASM)
Browser-nativeYes (IndexedDB)Needs WASM or server
Best forStructured text (requirements, decisions)Semantic/natural language
FuturePhase 2 may add embedding support via Orama plugin

UserProfileVectorStore

The user profile store captures and retrieves personal preferences across all projects.

Key details:

  • Singleton pattern (getInstance())
  • IndexedDB key: vector_store_user_profile
  • Language: English (BM25 stemming)
  • Auto-deduplication: On add(), performs BM25 search with threshold 0.8. If existing entry score > 0.8, updates timestamp/confidence/accessCount instead of inserting duplicate.

Schema:

typescript
{
  id: 'string',
  content: 'string',
  category: 'string',
  createdAt: 'string',
  updatedAt: 'string',
  accessCount: 'number',
  source: 'string',
  confidence: 'number'
}

Entry categories:

CategoryContent type
preference"User prefers TypeScript over JavaScript"
tech_stack"User uses React + Next.js stack"
coding_style"User prefers functional components with hooks"
domain_knowledge"User works in healthcare domain"
workflow"User prefers TDD workflow"
communication_style"User prefers brief responses"
project_preference"User likes mobile-first design"
generalGeneral knowledge about the user

formatContextForPrompt(query, maxTokens=500): Returns formatted strings like - [preference] User prefers TypeScript over JavaScript. Estimates tokens at 4 chars/token. Stops when budget exceeded.

ProjectContextVectorStore

The project context store captures and retrieves per-project knowledge — decisions, errors, patterns, requirements.

Key details:

  • Singleton pattern
  • Per-project isolation: Map<string, OramaDatabase> — each project gets its own Orama instance
  • IndexedDB keys: vector_store_project_{projectId} for each project
  • Language: English (BM25)

Schema:

typescript
{
  id: 'string',
  projectId: 'string',
  content: 'string',
  type: 'string',
  createdAt: 'string',
  updatedAt: 'string',
  sourceChatId: 'string',
  planPointId: 'string',
  files: 'string[]',
  tags: 'string[]'
}

Entry types:

TypeContent example
requirement"Login must support OAuth"
decision"Chose React Router over TanStack Router"
error"TypeError: Cannot read property 'id' of undefined"
fix"Fixed by adding null check before accessing id"
pattern"Using custom hooks for data fetching"
architecture"Monorepo with shared utils package"
constraint"Must support IE11 compatibility"
file_context"src/auth.ts handles OAuth flow"
conversation_summary"Discussed login implementation approach"
tool_usage"Used grep_search to find all auth references"
flow_definition"Login → Dashboard → Settings flow"
screen_connection"LoginScreen connects to DashboardScreen"

Priority ordering for formatContextForPrompt(projectId, query, maxTokens=1000): requirement > constraint > decision > error > fix > pattern > architecture > flow_definition > screen_connection > file_context

IndexedDB persistence

Vector stores persist in IndexedDB through a dedicated persistence layer (app/lib/vector-store/persistence.ts).

Database name: amplify_vector_stores (version 1) Object store: stores (keyPath: name)

Operations:

  • saveOramaToIDB(name, data) — Stores serialized Orama snapshot as JSON string
  • loadOramaFromIDB(name) — Returns null if not found
  • deleteOramaFromIDB(name) — Removes a store
  • listOramaDatabases() — Lists all stored databases

Serialization flow:

  • On save: Orama's native save(db) → JSON string → IDB
  • On load: Create new empty Orama instance → load(db, rawData) — NOT JSON.parse directly (which lacks Orama's internal methods)
Legacy MemoryStore

A legacy MemoryStore (app/lib/persistence/memoryStore.ts) coexists with the vector store:

  • Uses localStorage key amplify_user_memories
  • Simple substring search (case-insensitive)
  • Exact content deduplication (trim + lowercase match)
  • Both <user_memory> (legacy) and <user_context> (vector) injected into system prompt

Auto-extraction utilities

Amplify automatically extracts and stores facts from conversations:

extractAndStoreUserFacts(userMessage, assistantMessage):

  • Regex-based pattern matching for preferences: /i (prefer|like|want|use) .../
  • Tech stack detection: /(typescript|javascript|react|vue|svelte|...)/
  • Stored with confidence 0.9, source 'user_message'

extractAndStoreProjectContext(projId, actionDescription, type, files):

  • Called after file writes in workbench
  • Extracts requirements, decisions, patterns from AI actions
  • useVectorContext hook

    The useVectorContext hook (app/lib/hooks/useVectorContext.ts) manages context retrieval:

    1. Initialized on mount: Calls userProfileStore.initialize()
    2. Queries on message change: 300ms debounce search
    3. User profile: 500 token budget for BM25 search
    4. Project context: 1000 token budget for BM25 search
    5. Project detection: Uses chatId.get()projectStore.getProjectByChat()
    6. Returns: { userContext, projectContext, isReady, projectId }
    7. Passed to: useChat({ body: { userContext, projectContext } })

AI-callable vector store tools

Four MCP tools give the AI direct access to vector stores:

ToolStorePurpose
search_user_contextUserProfileVectorStoreBM25 search user preferences
store_user_factUserProfileVectorStoreStore new user preference (confidence 0.9)
search_project_contextProjectContextVectorStoreBM25 search project decisions/patterns
store_project_contextProjectContextVectorStoreStore project context entry

These tools are registered in the MCPService alongside native tools and memory tools. The AI can use them proactively to store information it learns about the user or project, and retrieve it later in the same or future sessions.

Learn about environment configuration