How to Self-Host Typesense with Docker Compose
What Is Typesense?
Typesense is an in-memory search engine designed for sub-millisecond search latency. It stores the entire search index in RAM for maximum speed, with automatic typo tolerance, faceting, and geo-search built in. Written in C++, it’s designed as a faster, easier alternative to Elasticsearch for application search. Think of it as Algolia that you self-host.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 1 GB+ RAM (scales with index size — 2-3x indexed data size)
- 5 GB+ free disk space
- No GPU required
Docker Compose Configuration
Create a docker-compose.yml file:
services:
typesense:
image: typesense/typesense:30.1
container_name: typesense
ports:
- "8108:8108"
volumes:
- typesense_data:/data
command: >
--data-dir /data
--api-key=your-api-key-change-this-to-something-strong
--enable-cors
restart: unless-stopped
volumes:
typesense_data:
Note: Typesense uses CLI arguments instead of environment variables for configuration.
Start the stack:
docker compose up -d
Initial Setup
Verify the Server
curl -H "X-TYPESENSE-API-KEY: your-api-key-change-this-to-something-strong" \
http://localhost:8108/health
Create a Collection (Schema)
Unlike Meilisearch, Typesense requires you to define a schema:
curl -X POST http://localhost:8108/collections \
-H "X-TYPESENSE-API-KEY: your-api-key-change-this-to-something-strong" \
-H "Content-Type: application/json" \
-d '{
"name": "movies",
"fields": [
{"name": "title", "type": "string"},
{"name": "genre", "type": "string", "facet": true},
{"name": "year", "type": "int32", "facet": true},
{"name": "rating", "type": "float", "optional": true}
],
"default_sorting_field": "year"
}'
Index Documents
curl -X POST http://localhost:8108/collections/movies/documents/import \
-H "X-TYPESENSE-API-KEY: your-api-key-change-this-to-something-strong" \
-H "Content-Type: text/plain" \
--data-binary '{"title": "The Matrix", "genre": "sci-fi", "year": 1999, "rating": 8.7}
{"title": "Interstellar", "genre": "sci-fi", "year": 2014, "rating": 8.7}
{"title": "The Dark Knight", "genre": "action", "year": 2008, "rating": 9.0}'
Search
curl "http://localhost:8108/collections/movies/search?q=matrx&query_by=title" \
-H "X-TYPESENSE-API-KEY: your-api-key-change-this-to-something-strong"
Typo tolerance is automatic — “matrx” finds “The Matrix”.
Configuration
Key CLI Arguments
| Argument | Default | Description |
|---|---|---|
--data-dir | Required | Directory for persistent data |
--api-key | Required | Admin API key |
--enable-cors | false | Enable CORS for browser requests |
--api-port | 8108 | HTTP API port |
--peering-port | 8107 | Port for cluster communication |
--thread-pool-size | 4 | Number of request handling threads |
--num-collections-parallel-load | 0 | Collections to load in parallel on startup |
--cache-num-entries | 1000 | Number of search results to cache |
--log-dir | Directory for log files |
Scoped API Keys
Create search-only API keys for frontend use:
curl -X POST http://localhost:8108/keys \
-H "X-TYPESENSE-API-KEY: your-api-key-change-this-to-something-strong" \
-H "Content-Type: application/json" \
-d '{
"description": "Search-only key",
"actions": ["documents:search"],
"collections": ["movies"]
}'
Advanced Configuration
Clustering (High Availability)
Typesense supports built-in Raft-based clustering:
services:
typesense-1:
image: typesense/typesense:30.1
command: >
--data-dir /data
--api-key=your-api-key
--nodes=/config/nodes.txt
--api-port=8108
--peering-port=8107
volumes:
- ts1_data:/data
- ./nodes.txt:/config/nodes.txt:ro
restart: unless-stopped
typesense-2:
image: typesense/typesense:30.1
command: >
--data-dir /data
--api-key=your-api-key
--nodes=/config/nodes.txt
--api-port=8108
--peering-port=8107
volumes:
- ts2_data:/data
- ./nodes.txt:/config/nodes.txt:ro
restart: unless-stopped
Create nodes.txt:
typesense-1:8107:8108,typesense-2:8107:8108
Vector Search
Typesense supports vector search for semantic similarity:
# Add a vector field to your collection
curl -X PATCH http://localhost:8108/collections/movies \
-H "X-TYPESENSE-API-KEY: your-api-key" \
-H "Content-Type: application/json" \
-d '{"fields": [{"name": "embedding", "type": "float[]", "num_dim": 384}]}'
Result Curation (Overrides)
Pin specific results for specific queries (useful for merchandising):
curl -X PUT "http://localhost:8108/collections/movies/overrides/featured-scifi" \
-H "X-TYPESENSE-API-KEY: your-api-key" \
-H "Content-Type: application/json" \
-d '{"rule": {"query": "best sci-fi", "match": "contains"}, "includes": [{"id": "1", "position": 1}]}'
Reverse Proxy
Configure your reverse proxy to forward to port 8108. See Reverse Proxy Setup.
Backup
Snapshots
Create a snapshot:
curl -X POST "http://localhost:8108/operations/snapshot?snapshot_path=/data/snapshots" \
-H "X-TYPESENSE-API-KEY: your-api-key"
Volume Backup
docker run --rm -v typesense_data:/data -v $(pwd):/backup alpine \
tar czf /backup/typesense-backup.tar.gz /data
See Backup Strategy.
Troubleshooting
High Memory Usage
Symptom: Typesense uses more RAM than expected. Fix: Typesense keeps the entire index in RAM. Expect 2-3x the size of your indexed fields. Remove unused fields from the schema. Consider Meilisearch if your dataset is too large for RAM.
Collection Creation Fails
Symptom: 400 error when creating a collection.
Fix: Check that all field types are valid (string, int32, int64, float, bool, string[], float[]). Ensure default_sorting_field references a numeric field.
Search Returns No Results
Symptom: Documents indexed but search finds nothing.
Fix: Verify query_by parameter references the correct field(s). Check that the field is of type string or string[] (non-string fields aren’t text-searchable).
Resource Requirements
- RAM: 2-3x the size of indexed data (in-memory engine)
- CPU: Low (C++ binary, very efficient)
- Disk: Index size + snapshot space
Verdict
Typesense is the fastest application search engine you can self-host. Sub-millisecond latency is real — and it makes search-as-you-type feel instant. The trade-off is RAM usage: keeping the entire index in memory means larger datasets get expensive. Built-in Raft clustering and result curation are standout features.
Choose Typesense for application search where speed is critical and your index fits in RAM. Choose Meilisearch for similar functionality with lower RAM usage (disk-based). Choose Elasticsearch for analytics, logging, and massive-scale search.
Related
Get self-hosting tips in your inbox
New guides, comparisons, and setup tutorials — delivered weekly. No spam.