← All articles
DEVELOPMENT Self-Hosting Typesense: A Fast, Typo-Tolerant Search... 2026-02-09 · typesense · search · full-text-search

Self-Hosting Typesense: A Fast, Typo-Tolerant Search Engine

Development 2026-02-09 typesense search full-text-search api development

Search is one of those features that's easy to build poorly and hard to build well. A SQL LIKE query doesn't handle typos, doesn't rank results intelligently, and slows down as your dataset grows. Elasticsearch handles all of that, but it's a distributed system that demands gigabytes of RAM and serious operational knowledge.

Typesense sits in the middle. It's a search engine purpose-built for speed and simplicity — written in C++ for raw performance, typo-tolerant by default, and deployable in minutes. It's the closest thing to "Algolia but self-hosted."

Why Typesense?

The schema-enforced approach is the key philosophical difference from Meilisearch. Typesense makes you define your collection schema upfront (types for each field), which catches data issues early but requires more initial setup.

Frontend Search-only API key Backend Admin API key search index Typesense Schema-enforced search In-memory index (C++) Typo tolerance & ranking Data Volume HA Cluster (optional) Node 1 (leader) Node 2 (replica) Node 3 (replica) Raft sync

Docker Deployment

# docker-compose.yml
services:
  typesense:
    image: typesense/typesense:27.1
    ports:
      - "8108:8108"
    volumes:
      - typesense_data:/data
    command: >
      --data-dir /data
      --api-key=your-admin-api-key
      --enable-cors
    restart: unless-stopped

volumes:
  typesense_data:
docker compose up -d

Typesense is running at http://your-server:8108. The --api-key flag sets your admin API key.

Creating a Collection

Typesense requires you to define a schema before indexing documents. This is different from Meilisearch's schemaless approach.

curl 'http://localhost:8108/collections' \
  -X POST \
  -H 'X-TYPESENSE-API-KEY: your-admin-api-key' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "products",
    "fields": [
      {"name": "name", "type": "string"},
      {"name": "description", "type": "string"},
      {"name": "category", "type": "string", "facet": true},
      {"name": "price", "type": "float"},
      {"name": "rating", "type": "float", "optional": true},
      {"name": "in_stock", "type": "bool", "facet": true}
    ],
    "default_sorting_field": "rating"
  }'

The facet: true flag enables filtering and faceted search on that field. The default_sorting_field determines how results are ranked when no explicit sort is specified.

Indexing Documents

curl 'http://localhost:8108/collections/products/documents' \
  -X POST \
  -H 'X-TYPESENSE-API-KEY: your-admin-api-key' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Ergonomic Keyboard",
    "description": "Split mechanical keyboard with Cherry MX switches",
    "category": "Electronics",
    "price": 149.99,
    "rating": 4.7,
    "in_stock": true
  }'

For bulk indexing, use the import endpoint with JSONL format:

curl 'http://localhost:8108/collections/products/documents/import?action=upsert' \
  -X POST \
  -H 'X-TYPESENSE-API-KEY: your-admin-api-key' \
  -H 'Content-Type: text/plain' \
  -d '{"name":"Ergonomic Keyboard","description":"Split mechanical keyboard","category":"Electronics","price":149.99,"rating":4.7,"in_stock":true}
{"name":"USB-C Monitor","description":"32-inch 4K display with USB-C","category":"Electronics","price":399.99,"rating":4.5,"in_stock":true}'

Searching

curl 'http://localhost:8108/collections/products/documents/search' \
  -H 'X-TYPESENSE-API-KEY: your-admin-api-key' \
  -G \
  -d 'q=ergnomic keybard' \
  -d 'query_by=name,description' \
  -d 'filter_by=category:=Electronics&&price:<200' \
  -d 'sort_by=rating:desc'

The typos in "ergnomic keybard" are handled automatically. Typesense returns the "Ergonomic Keyboard" as expected.

Faceted search

Facets let you build filter menus (like "Category: Electronics (12), Office (8)"):

curl 'http://localhost:8108/collections/products/documents/search' \
  -H 'X-TYPESENSE-API-KEY: your-admin-api-key' \
  -G \
  -d 'q=*' \
  -d 'query_by=name' \
  -d 'facet_by=category,in_stock'

The response includes facet counts for each category and stock status — ready to render as filter checkboxes in your UI.

Scoped API Keys

Never expose your admin API key to the frontend. Create scoped search-only keys:

curl 'http://localhost:8108/keys' \
  -X POST \
  -H 'X-TYPESENSE-API-KEY: your-admin-api-key' \
  -H 'Content-Type: application/json' \
  -d '{
    "description": "Search-only key",
    "actions": ["documents:search"],
    "collections": ["products"]
  }'

Use this key in your frontend JavaScript. It can only search, never modify data.

Instant Search UI

Typesense provides an InstantSearch adapter that works with Algolia's open-source InstantSearch.js library:

<script src="https://cdn.jsdelivr.net/npm/typesense-instantsearch-adapter/dist/typesense-instantsearch-adapter.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js"></script>
const typesenseAdapter = new TypesenseInstantSearchAdapter({
  server: {
    apiKey: 'your-search-only-key',
    nodes: [{ host: 'search.yourdomain.com', port: 443, protocol: 'https' }]
  },
  additionalSearchParameters: {
    query_by: 'name,description'
  }
});

const search = instantsearch({
  indexName: 'products',
  searchClient: typesenseAdapter.searchClient
});

This gives you a polished search UI with as-you-type results, facet filters, and pagination without building it from scratch.

High Availability Clustering

For production use, Typesense supports a 3-node cluster with Raft consensus:

services:
  typesense-1:
    image: typesense/typesense:27.1
    command: >
      --data-dir /data
      --api-key=your-admin-api-key
      --nodes=/config/nodes.txt
      --peering-address=typesense-1
      --peering-port=8107
    volumes:
      - ts1_data:/data
      - ./nodes.txt:/config/nodes.txt

  typesense-2:
    image: typesense/typesense:27.1
    command: >
      --data-dir /data
      --api-key=your-admin-api-key
      --nodes=/config/nodes.txt
      --peering-address=typesense-2
      --peering-port=8107
    volumes:
      - ts2_data:/data
      - ./nodes.txt:/config/nodes.txt

Create nodes.txt:

typesense-1:8107:8108,typesense-2:8107:8108,typesense-3:8107:8108

Typesense vs Meilisearch vs Elasticsearch

Feature Typesense Meilisearch Elasticsearch
Language C++ Rust Java
Schema Required Optional Optional
Typo tolerance Built-in Built-in Manual config
RAM usage (small) ~100 MB ~100 MB ~2-4 GB
Clustering Built-in (Raft) Not yet Built-in
Geo search Yes Yes Yes
Faceted search Yes Yes Yes
InstantSearch compat Yes (adapter) Yes (adapter) Yes (native)
License GPL-3.0 MIT SSPL

When to choose Typesense

When to choose Meilisearch

The Bottom Line

Typesense is the self-hosted search engine for teams that want production-grade reliability with minimal fuss. The schema-enforced approach catches errors before they reach your search index, the built-in clustering provides real high availability, and the InstantSearch compatibility means you can build a polished search UI in an afternoon. If you're currently paying for Algolia or fighting with Elasticsearch, Typesense gives you fast, typo-tolerant search that runs on your own infrastructure.