Skip to main content

FTS5 Full-Text Search

How Synapse uses SQLite FTS5 for sub-millisecond full-text memory search.


FTS5 Full-Text Search

Synapse uses FTS5 (Full-Text Search 5) for fast, flexible memory search. This page explains how it works and how to use it effectively.

What is FTS5?

FTS5 is a SQLite extension (also available in PostgreSQL via extensions) that provides full-text search capabilities. It:

  • Indexes text content for fast keyword search
  • Supports boolean operators (AND, OR, NOT)
  • Supports phrase matching with quotes
  • Supports prefix matching with *
  • Ranks results by relevance

Synapse uses FTS5 to index all memory content, enabling sub-millisecond search across thousands of memories.

How Synapse Uses FTS5

When you POST /memory:

  1. Memory content is stored in the memories table
  2. Content is also inserted into the FTS5 virtual table
  3. FTS5 automatically tokenizes and indexes the content

When you GET /memory/search?q=...:

  1. Synapse parses the query using FTS5 syntax
  2. Executes a MATCH against the FTS5 index
  3. Filters by mind_id (tenant isolation)
  4. Returns ranked results

Query Syntax

Simple keyword search

?q=docker

Returns memories containing "docker".

Multiple keywords (implicit AND)

?q=docker+swarm
?q=docker%20swarm

Returns memories containing BOTH "docker" AND "swarm".

Phrase matching

?q="docker+swarm"
?q=%22docker%20swarm%22

Returns memories containing the exact phrase "docker swarm".

Prefix matching

?q=docker*

Returns memories containing words starting with "docker" (e.g. "dockers", "dockerfile", "dockerize").

Boolean OR

?q=docker+OR+kubernetes

Returns memories containing "docker" OR "kubernetes".

Boolean NOT

?q=docker+-swarm
?q=docker+NOT+swarm

Returns memories containing "docker" but NOT "swarm".

Grouping

?q=(docker+OR+kubernetes)+-test

Returns memories containing "docker" or "kubernetes", but not "test".

Practical Examples

Find memories about a project

curl -H "Authorization: Bearer YOUR_MIND_KEY" \
     "https://synapse.schaefer.zone/memory/search?q=synapse+deployment"

Find exact phrase

curl -H "Authorization: Bearer YOUR_MIND_KEY" \
     "https://synapse.schaefer.zone/memory/search?q=%22docker+swarm%22"

Exclude test memories

curl -H "Authorization: Bearer YOUR_MIND_KEY" \
     "https://synapse.schaefer.zone/memory/search?q=production+-test"

Find by technology

curl -H "Authorization: Bearer YOUR_MIND_KEY" \
     "https://synapse.schaefer.zone/memory/search?q=(postgres+OR+sqlite)+-mysql"

Ranking

FTS5 ranks results by relevance using BM25 algorithm. Factors:

  • Term frequency (how often the term appears)
  • Inverse document frequency (rarer terms rank higher)
  • Document length (shorter docs with the term rank higher)
  • Column weight (title > content)

Results are returned in rank order (most relevant first).

Performance

Operation Latency
Search 100 memories < 5ms
Search 1,000 memories < 10ms
Search 10,000 memories < 25ms
Search 100,000 memories < 100ms

FTS5 is highly optimized for read-heavy workloads.

Limitations

Stemming

FTS5 doesn't do stemming by default. "running" and "run" are different terms.

Workaround: Use prefix matching: ?q=run*

Typo tolerance

FTS5 doesn't support fuzzy matching. A typo will return no results.

Workaround: Use semantic search (/memory/semantic-search) for conceptual matching.

Stop words

Common words (the, a, an, is) are indexed but may not be useful for search. FTS5 handles this automatically.

FTS5 vs Semantic Search

Aspect FTS5 Semantic Search
Speed Sub-millisecond 50-100ms
Matching Exact keywords Conceptual
Typo tolerance None Some
Stemming None Implicit
Requires embeddings No Yes
Best for Specific terms Concepts

Use FTS5 when you know the keywords. Use semantic search when you want "memories about X" where X is described differently.

Best Practices

Next Steps