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:
- UserProfileVectorStore : User preferences, tech stack, coding style
- 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
| Aspect | BM25 (Orama) | Embedding Search |
| Algorithm | Keyword frequency + TF-IDF | Cosine similarity of dense vectors |
| Requires model | No | Yes (additional API call) |
| Deterministic | Yes | No (depends on embedding model) |
| Bundle size | ~2KB | ~200KB+ (WASM) |
| Browser-native | Yes (IndexedDB) | Needs WASM or server |
| Best for | Structured text (requirements, decisions) | Semantic/natural language |
| Future | Phase 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:
{
id: 'string',
content: 'string',
category: 'string',
createdAt: 'string',
updatedAt: 'string',
accessCount: 'number',
source: 'string',
confidence: 'number'
}
Entry categories:
| Category | Content 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" |
general | General 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:
{
id: 'string',
projectId: 'string',
content: 'string',
type: 'string',
createdAt: 'string',
updatedAt: 'string',
sourceChatId: 'string',
planPointId: 'string',
files: 'string[]',
tags: 'string[]'
}
Entry types:
| Type | Content 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 stringloadOramaFromIDB(name)— Returns null if not founddeleteOramaFromIDB(name)— Removes a storelistOramaDatabases()— 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)— NOTJSON.parsedirectly (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
useVectorContexthook (app/lib/hooks/useVectorContext.ts) manages context retrieval:- Initialized on mount: Calls
userProfileStore.initialize() - Queries on message change: 300ms debounce search
- User profile: 500 token budget for BM25 search
- Project context: 1000 token budget for BM25 search
- Project detection: Uses
chatId.get()→projectStore.getProjectByChat() - Returns:
{ userContext, projectContext, isReady, projectId } - Passed to:
useChat({ body: { userContext, projectContext } })
- Initialized on mount: Calls
AI-callable vector store tools
Four MCP tools give the AI direct access to vector stores:
| Tool | Store | Purpose |
search_user_context | UserProfileVectorStore | BM25 search user preferences |
store_user_fact | UserProfileVectorStore | Store new user preference (confidence 0.9) |
search_project_context | ProjectContextVectorStore | BM25 search project decisions/patterns |
store_project_context | ProjectContextVectorStore | Store 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