Why Self-Host Your Search Engine on a VPS
A dedicated search engine replaces slow LIKE '%...%' queries with instant search that is typo-tolerant and ranked by relevance. Self-hosting it on a VPS spares you the per-search or per-document billing of SaaS solutions and keeps your index (and therefore your customer data, your catalog) on your own infrastructure. Meilisearch and Typesense are designed for 'search-as-you-type': responses in a few milliseconds, a simple REST API, typo tolerance, and facets included. Meilisearch shines with its ease of use and default relevance quality; Typesense emphasizes raw performance, fine-grained ranking control, and high-availability clustering. Both keep the index in RAM, which directly sizes your VPS.
The Strengths of a Self-Hosted Search Engine
- Instant search with typo tolerance, without coding the algorithm
- No billing per indexed document or per query
- Index and business data kept on your VPS
- Facets, filters, and sorting to build rich catalog interfaces
- A REST API and scoped keys for secure frontend-side use
- Synonyms and relevance rules adjustable to your business vocabulary
Prerequisites: RAM Above All
These engines keep the active index in memory: RAM is the critical resource. For a few tens of thousands of documents, 1 to 2 GB of RAM and 1 vCPU are enough. For hundreds of thousands to a few million documents with facets, aim for 4 GB and 2 vCPUs. An SSD disk speeds up persistence and reloading at startup. You'll need Docker and Compose, a subdomain (search.yourdomain.com) if you expose the API to the frontend, and a reverse proxy for TLS. Plan for a strong master key and search keys with limited scope so that you never expose the admin key on the browser side.
Deploy Meilisearch (or Typesense) on a VPS
Define the Docker Service
Declare getmeili/meilisearch (or typesense/typesense), mount a volume for index persistence, and pass the master key via an environment variable (MEILI_MASTER_KEY or TYPESENSE_API_KEY). Bind port 7700/8108 locally only.
Launch and Check Health
Run docker compose up -d, then test curl http://127.0.0.1:7700/health. An available response confirms that the engine is ready to receive documents.
Create the Index and Feed in the Data
Send your documents as JSON through the API (POST to /indexes/produits/documents). Define the searchable, filterable, and sortable attributes; in a search engine, the declaration order of the searchable attributes directly influences relevance.
Expose the API Behind a Reverse Proxy
Proxy search.yourdomain.com to the local port with Caddy or Nginx for HTTPS. Enable CORS only toward your application domain so that only your frontend queries the engine.
Generate Scoped Keys
Create a key limited to search operations on a given index, to be used on the browser side. The master key must never leave the server or appear in the frontend code.
Sync with Your Database
Set up a job (webhook or scheduled task) that pushes creations and updates to the index on every database change, to keep search consistent with the source of truth.
| Criterion | Meilisearch | Typesense |
|---|---|---|
| Getting started | Very simple, excellent default relevance | Simple, more explicit control |
| Typo tolerance | Native and tunable | Native, configurable per field |
| Ranking control | Ordered ranking rules | Very granular (per-field ranking, weights) |
| Facets / filters | Complete | Complete and high-performance |
| High availability | Replication evolving | Built-in Raft clustering |
| Memory usage | Moderate | Optimized, often more frugal |
| Vector search | Supported | Supported |
| Language / deployment | Rust, single binary | C++, single binary |
Before oversizing your VPS, only index the fields that are actually searchable. Storing a large, full HTML text in the index needlessly inflates RAM: index the title, the tags, and a summary, and keep the heavy content in the database, fetched after the click. You'll often cut the memory footprint by half or a third for identical relevance.