Typesense

Fast and typo-tolerant open-source search engine. Supports instant search experience, geo-search, and faceted search. Lightweight alternative to Elasticsearch.

Search EngineOpen SourceFast SearchReal-timeTypo ToleranceRESTfulDeveloper-friendlyVector Search

Server

Typesense

Overview

Typesense is a fast, developer-friendly open-source search engine built in C++. Featuring sub-millisecond search responses, excellent typo tolerance, and support for vector and hybrid search, it provides an intuitive API that's easy to set up. With its in-memory architecture enabling ultra-fast search and real-time index updates, it delivers exceptional user experiences.

Details

Typesense 2024 edition features vector search, hybrid search (vector + keyword), conversational search, multi-language typo tolerance, advanced filtering, geospatial search, and real-time analytics capabilities. Built with an optimized C++ architecture that significantly outperforms Elasticsearch and Solr in search performance, it provides intuitive REST APIs and GraphQL support for rapid implementation.

Key Features

  • Ultra-Fast Search: Sub-millisecond search responses through in-memory architecture
  • AI Capabilities: Vector search and hybrid search for semantic search functionality
  • Powerful Typo Tolerance: Advanced spell correction and fuzzy matching
  • Real-time Processing: Real-time indexing and query processing
  • Multi-language Support: Comprehensive internationalization support and language-specific optimizations
  • Geospatial Search: High-performance geo-search and location-based filtering

Pros and Cons

Pros

  • Simple setup with intuitive APIs providing high development efficiency
  • Dramatically faster search performance compared to Elasticsearch and Solr
  • Cost reduction and technical freedom through open-source nature
  • High performance with small footprint and low resource consumption
  • Easy implementation of comprehensive search features (facets, filtering, sorting)
  • Complete data control with self-hosted deployment options

Cons

  • Increased memory usage due to in-memory architecture
  • Limited distributed processing capabilities for large datasets compared to Elasticsearch
  • Smaller plugin ecosystem compared to other mature search engines
  • May underperform Elasticsearch in complex analytical queries
  • Limited commercial support options
  • Some enterprise-grade features may have constraints for large-scale deployments

Reference Pages

Code Examples

Setup and Installation

# Docker execution
docker run -p 8108:8108 -v /tmp/typesense-data:/data typesense/typesense:0.25.2 \
  --data-dir /data --api-key=xyz --enable-cors

# macOS installation (Homebrew)
brew install typesense-server

# Linux binary installation
wget https://dl.typesense.org/releases/0.25.2/typesense-server-0.25.2-linux-amd64.tar.gz
tar -xzf typesense-server-0.25.2-linux-amd64.tar.gz
cd typesense-server-0.25.2-linux-amd64

# Server startup
./typesense-server --data-dir=/tmp/typesense-data --api-key=xyz --enable-cors

# Docker Compose configuration
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
  typesense:
    image: typesense/typesense:0.25.2
    ports:
      - "8108:8108"
    volumes:
      - ./typesense-data:/data
    command: '--data-dir /data --api-key=your-api-key --enable-cors'
    environment:
      - TYPESENSE_API_KEY=your-secure-api-key
      - TYPESENSE_DATA_DIR=/data
    restart: unless-stopped
EOF

docker-compose up -d

# Kubernetes deployment
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: typesense
spec:
  replicas: 3
  selector:
    matchLabels:
      app: typesense
  template:
    metadata:
      labels:
        app: typesense
    spec:
      containers:
      - name: typesense
        image: typesense/typesense:0.25.2
        ports:
        - containerPort: 8108
        env:
        - name: TYPESENSE_API_KEY
          valueFrom:
            secretKeyRef:
              name: typesense-secret
              key: api-key
        args:
        - --data-dir=/data
        - --api-key=$(TYPESENSE_API_KEY)
        - --enable-cors
        volumeMounts:
        - name: data
          mountPath: /data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: typesense-pvc
EOF

Collection Creation and Document Management

# Create collection schema
curl -X POST "http://localhost:8108/collections" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "movies",
    "fields": [
      {"name": "id", "type": "string"},
      {"name": "title", "type": "string"},
      {"name": "overview", "type": "string"},
      {"name": "genre", "type": "string[]"},
      {"name": "release_date", "type": "int64"},
      {"name": "rating", "type": "float"},
      {"name": "director", "type": "string"},
      {"name": "duration", "type": "int32"},
      {"name": "location", "type": "geopoint"},
      {"name": "embedding", "type": "float[]", "num_dim": 384}
    ],
    "default_sorting_field": "rating"
  }'

# Add single document
curl -X POST "http://localhost:8108/collections/movies/documents" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "1",
    "title": "The Shawshank Redemption",
    "overview": "Two imprisoned men bond over a number of years",
    "genre": ["Drama", "Crime"],
    "release_date": 748569600,
    "rating": 9.3,
    "director": "Frank Darabont",
    "duration": 142,
    "location": [41.1179, -81.6804]
  }'

# Bulk import multiple documents (JSONL format)
curl -X POST "http://localhost:8108/collections/movies/documents/import" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @- << 'EOF'
{"id": "2", "title": "The Godfather", "overview": "The aging patriarch of an organized crime dynasty", "genre": ["Drama", "Crime"], "release_date": 69379200, "rating": 9.2, "director": "Francis Ford Coppola", "duration": 175}
{"id": "3", "title": "The Dark Knight", "overview": "Batman begins his war on crime", "genre": ["Action", "Crime", "Drama"], "release_date": 1216339200, "rating": 9.0, "director": "Christopher Nolan", "duration": 152}
{"id": "4", "title": "Pulp Fiction", "overview": "The lives of two mob hitmen intertwine", "genre": ["Crime", "Drama"], "release_date": 782092800, "rating": 8.9, "director": "Quentin Tarantino", "duration": 154}
EOF

# Update document
curl -X PATCH "http://localhost:8108/collections/movies/documents/1" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "rating": 9.4,
    "updated_at": 1705392000
  }'

# Delete document
curl -X DELETE "http://localhost:8108/collections/movies/documents/1" \
  -H "X-TYPESENSE-API-KEY: xyz"

# Get document
curl -X GET "http://localhost:8108/collections/movies/documents/1" \
  -H "X-TYPESENSE-API-KEY: xyz"

Search Query Implementation

# Basic search
curl -X GET \
  "http://localhost:8108/collections/movies/documents/search?q=shawshank&query_by=title,overview" \
  -H "X-TYPESENSE-API-KEY: xyz"

# Advanced search options
curl -X GET \
  "http://localhost:8108/collections/movies/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -G \
  -d "q=crime drama" \
  -d "query_by=title,overview,director" \
  -d "filter_by=rating:>=8.0 && genre:Crime" \
  -d "sort_by=rating:desc,release_date:desc" \
  -d "facet_by=genre,director" \
  -d "max_facet_values=10" \
  -d "per_page=20" \
  -d "page=1" \
  -d "highlight_full_fields=title,overview" \
  -d "snippet_threshold=15" \
  -d "typo_tokens_threshold=1" \
  -d "drop_tokens_threshold=2"

# Faceted search
curl -X GET \
  "http://localhost:8108/collections/movies/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -G \
  -d "q=*" \
  -d "query_by=title" \
  -d "facet_by=genre,director,release_date" \
  -d "max_facet_values=20" \
  -d "facet_query=genre:Drama"

# Geospatial search
curl -X GET \
  "http://localhost:8108/collections/theaters/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -G \
  -d "q=cinema" \
  -d "query_by=name,description" \
  -d "filter_by=location:(40.7589, -73.9851, 5 km)" \
  -d "sort_by=location(40.7589, -73.9851):asc"

# Multi-search
curl -X POST "http://localhost:8108/multi_search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "searches": [
      {
        "collection": "movies",
        "q": "action",
        "query_by": "title,overview",
        "filter_by": "rating:>=8.0"
      },
      {
        "collection": "books", 
        "q": "science fiction",
        "query_by": "title,description"
      }
    ]
  }'

# Fuzzy search (typo tolerance)
curl -X GET \
  "http://localhost:8108/collections/movies/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -G \
  -d "q=shawshenk redemtion" \
  -d "query_by=title,overview" \
  -d "typo_tokens_threshold=1" \
  -d "num_typos=2" \
  -d "min_len_1typo=4" \
  -d "min_len_2typo=7"

Vector Search and AI Features

# Create collection for vector search
curl -X POST "http://localhost:8108/collections" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "documents",
    "fields": [
      {"name": "id", "type": "string"},
      {"name": "title", "type": "string"},
      {"name": "content", "type": "string"},
      {"name": "embedding", "type": "float[]", "num_dim": 384}
    ]
  }'

# Execute vector search
curl -X GET \
  "http://localhost:8108/collections/documents/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -G \
  -d "q=*" \
  -d "vector_query=embedding:([0.1, 0.2, 0.3, ...], k:10)" \
  -d "per_page=10"

# Hybrid search (text + vector)
curl -X GET \
  "http://localhost:8108/collections/documents/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -G \
  -d "q=artificial intelligence" \
  -d "query_by=title,content" \
  -d "vector_query=embedding:([0.15, 0.25, 0.35, ...], k:10)" \
  -d "rank_tokens_by=default_score" \
  -d "per_page=10"

# Semantic search configuration
curl -X POST "http://localhost:8108/collections" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "semantic_search",
    "fields": [
      {"name": "id", "type": "string"},
      {"name": "title", "type": "string"},
      {"name": "content", "type": "string"},
      {"name": "embedding", "type": "float[]", "num_dim": 768, "embed": {"from": ["title", "content"], "model_config": {"model_name": "ts/all-MiniLM-L12-v2"}}}
    ]
  }'

# Search with automatic embeddings
curl -X GET \
  "http://localhost:8108/collections/semantic_search/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -G \
  -d "q=machine learning applications" \
  -d "query_by=embedding" \
  -d "per_page=10"

Performance Optimization

# Check collection statistics
curl -X GET "http://localhost:8108/collections/movies" \
  -H "X-TYPESENSE-API-KEY: xyz"

# Monitor search performance
curl -X GET "http://localhost:8108/stats.json" \
  -H "X-TYPESENSE-API-KEY: xyz"

# Check memory usage
curl -X GET "http://localhost:8108/debug" \
  -H "X-TYPESENSE-API-KEY: xyz"

# Configuration optimization (server startup)
./typesense-server \
  --data-dir=/data \
  --api-key=xyz \
  --enable-cors \
  --num-memory-shards=4 \
  --search-only-mode=false \
  --healthy-read-lag=1000 \
  --healthy-write-lag=1000 \
  --log-level=INFO \
  --max-memory-ratio=0.8

# Cache configuration
curl -X POST "http://localhost:8108/collections/movies/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "action",
    "query_by": "title,overview",
    "cache_ttl": 300
  }'

# Index optimization
curl -X POST "http://localhost:8108/collections/movies/compact" \
  -H "X-TYPESENSE-API-KEY: xyz"

SDK and Framework Integration

// JavaScript/Node.js SDK
import { Client as TypesenseClient } from 'typesense'

const client = new TypesenseClient({
  'nodes': [{
    'host': 'localhost',
    'port': '8108',
    'protocol': 'http'
  }],
  'apiKey': 'xyz',
  'connectionTimeoutSeconds': 2
})

// Create collection
const moviesSchema = {
  'name': 'movies',
  'fields': [
    {'name': 'id', 'type': 'string'},
    {'name': 'title', 'type': 'string'},
    {'name': 'overview', 'type': 'string'},
    {'name': 'genre', 'type': 'string[]'},
    {'name': 'rating', 'type': 'float'},
    {'name': 'release_date', 'type': 'int64'}
  ],
  'default_sorting_field': 'rating'
}

await client.collections().create(moviesSchema)

// Add documents
const documents = [
  {
    'id': '1',
    'title': 'The Shawshank Redemption',
    'overview': 'Two imprisoned men bond over a number of years',
    'genre': ['Drama', 'Crime'],
    'rating': 9.3,
    'release_date': 748569600
  }
]

await client.collections('movies').documents().import(documents)

// Execute search
const searchResults = await client
  .collections('movies')
  .documents()
  .search({
    'q': 'shawshank',
    'query_by': 'title,overview',
    'filter_by': 'rating:>=8.0',
    'sort_by': 'rating:desc'
  })

console.log(searchResults.hits)

// Real-time search (instant search)
const searchParams = {
  'q': 'sha',
  'query_by': 'title,overview',
  'typo_tokens_threshold': 1,
  'prefix': true,
  'per_page': 5
}

const instantResults = await client
  .collections('movies')
  .documents()
  .search(searchParams)
# Python SDK
import typesense

client = typesense.Client({
  'nodes': [{
    'host': 'localhost',
    'port': '8108',
    'protocol': 'http'
  }],
  'api_key': 'xyz',
  'connection_timeout_seconds': 2
})

# Create collection
movies_schema = {
  'name': 'movies',
  'fields': [
    {'name': 'id', 'type': 'string'},
    {'name': 'title', 'type': 'string'},
    {'name': 'overview', 'type': 'string'},
    {'name': 'genre', 'type': 'string[]'},
    {'name': 'rating', 'type': 'float'},
    {'name': 'release_date', 'type': 'int64'}
  ],
  'default_sorting_field': 'rating'
}

client.collections.create(movies_schema)

# Add documents
documents = [
  {
    'id': '1',
    'title': 'The Shawshank Redemption',
    'overview': 'Two imprisoned men bond over a number of years',
    'genre': ['Drama', 'Crime'],
    'rating': 9.3,
    'release_date': 748569600
  }
]

client.collections['movies'].documents.import_(documents)

# Execute search
search_results = client.collections['movies'].documents.search({
  'q': 'shawshank',
  'query_by': 'title,overview',
  'filter_by': 'rating:>=8.0',
  'sort_by': 'rating:desc'
})

print(search_results['hits'])

# Advanced search
advanced_search = client.collections['movies'].documents.search({
  'q': 'crime',
  'query_by': 'title,overview,director',
  'filter_by': 'genre:Crime && rating:>=8.0',
  'facet_by': 'genre,director',
  'sort_by': 'rating:desc',
  'typo_tokens_threshold': 1,
  'prefix': True,
  'per_page': 10
})

Advanced Configuration and Cluster Setup

# High availability setup (3-node cluster)
# Node 1
./typesense-server \
  --data-dir=/data/node1 \
  --api-key=xyz \
  --peering-address=192.168.1.100 \
  --peering-port=8107 \
  --api-port=8108 \
  --nodes=192.168.1.100:8107:8108,192.168.1.101:8107:8108,192.168.1.102:8107:8108

# Node 2  
./typesense-server \
  --data-dir=/data/node2 \
  --api-key=xyz \
  --peering-address=192.168.1.101 \
  --peering-port=8107 \
  --api-port=8108 \
  --nodes=192.168.1.100:8107:8108,192.168.1.101:8107:8108,192.168.1.102:8107:8108

# Node 3
./typesense-server \
  --data-dir=/data/node3 \
  --api-key=xyz \
  --peering-address=192.168.1.102 \
  --peering-port=8107 \
  --api-port=8108 \
  --nodes=192.168.1.100:8107:8108,192.168.1.101:8107:8108,192.168.1.102:8107:8108

# Replication configuration
curl -X PATCH "http://localhost:8108/collections/movies" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "replication_factor": 3
  }'

# Create backup
curl -X POST "http://localhost:8108/snapshots" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -d '{
    "snapshot_path": "/backups/snapshot_$(date +%Y%m%d_%H%M%S)"
  }'

# SSL/TLS configuration
./typesense-server \
  --data-dir=/data \
  --api-key=xyz \
  --ssl-certificate=/path/to/certificate.pem \
  --ssl-certificate-key=/path/to/private.key \
  --enable-cors

# API rate limiting
curl -X POST "http://localhost:8108/collections/movies/documents/search" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "X-TYPESENSE-USER-ID: user123" \
  -H "Content-Type: application/json" \
  -d '{
    "q": "search query",
    "query_by": "title"
  }'

# Health monitoring
curl -X GET "http://localhost:8108/health" \
  -H "X-TYPESENSE-API-KEY: xyz"

# Metrics collection
curl -X GET "http://localhost:8108/metrics.json" \
  -H "X-TYPESENSE-API-KEY: xyz"

Analytics and Monitoring

# Search analytics
curl -X GET "http://localhost:8108/analytics/events" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -G \
  -d "type=search" \
  -d "from=2024-01-01" \
  -d "to=2024-01-31"

# Popular searches
curl -X GET "http://localhost:8108/analytics/rules" \
  -H "X-TYPESENSE-API-KEY: xyz"

# Click analytics
curl -X POST "http://localhost:8108/analytics/events" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "click",
    "data": {
      "q": "batman",
      "collections": ["movies"],
      "search_id": "search_123",
      "user_id": "user_456",
      "object_id": "movie_789",
      "position": 1
    }
  }'

# Conversion tracking
curl -X POST "http://localhost:8108/analytics/events" \
  -H "X-TYPESENSE-API-KEY: xyz" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "conversion",
    "data": {
      "search_id": "search_123",
      "user_id": "user_456",
      "object_id": "movie_789",
      "conversion_type": "purchase"
    }
  }'

Typesense is a modern search engine that prioritizes ultra-fast performance and simplicity, delivering exceptional performance especially for real-time search and typo tolerance functionality. It offers an excellent choice for achieving high-performance search capabilities with low resource consumption while leveraging the benefits of open-source software.