CodeWorlds
Back to collections
Guide18 min readCodeWorlds Team

Typesense, a search engine under the GPL

Typesense is a C++ search engine with typo tolerance. Version 30.2, the GPL-3.0 licence and what it implies, Raft clustering and real cloud rates.

Typesense, a search engine under the GPL

Typesense is a search engine written in C++ that keeps its index in memory and forgives typos in the query by default. The current version is 30.2, released on 19 April 2026, the typesense/typesense repository holds roughly 26.5 thousand stars, and the licence is version three of the GPL, which sets it apart from its permissive competitors and carries real consequences for some forms of distribution.

What Typesense actually does

The whole thing is one executable that exposes an API over HTTP and speaks JSON in both directions. There is no virtual machine to configure, no separate coordinating process, no plugin layer. You start the binary pointing at a data directory and an admin key, and moments later it answers on port 8108.

Data is organised into collections, the equivalent of tables, with an explicitly declared field schema. Every field has a type, and extra flags decide whether you can filter, facet and sort on it. Documents go in one at a time or in bulk as JSONL, and the index updates immediately, with no separate segment merge step.

Search covers typo-tolerant matching enabled by default, filtering on fields, facets with counts, result grouping, synonyms, manually pinning chosen records to the top, geographic queries, vector matching and a hybrid mode combining the last two with the first. A separate multi_search endpoint lets you send several queries in one HTTP request, which saves a good deal of network round trips in an interface with more than one suggestion box.

The key architectural trait is easy to state: the index lives in main memory. That is where the predictable latency comes from, since no query waits on a disk, and that is also where the main operating cost comes from, since the size of the dataset translates straight into the size of the machine. Planning a Typesense deployment starts with the question of how much memory the fields you actually index will take.

What Typesense does not do matters just as much. It is not a transactional database and does not replace PostgreSQL as the source of truth, so your data still lives elsewhere and is synchronised into the index. Nor is it a specialised vector database in the sense of Qdrant or Pinecone, even though it does handle vector search. It also has no analytics and aggregation layer in the style of Elasticsearch, because the scope is deliberately narrow.

The position of this tool sits precisely in the middle. It differs from Meilisearch in that replication and cluster operation are part of the open version. It differs from Elasticsearch in that you need not learn a model of nodes, shards and roles before running your first query.

Version, licence and what the GPL changes in practice

Version 30.2 arrived on 19 April 2026, the same day as the 29.1 patch release. The repository is alive: the last change on the main branch dates from 18 August 2026, there are 962 forks and 869 open issues, and the project is not archived. The Typesense Cloud calculator offers version 30.2, 29.1 and a whole series of 31.0.rc candidates, so the next major release can be tested on a managed cluster before it ships.

The licence looks the same from every angle, which after other projects in this collection is a pleasant change. The LICENSE.txt file in the repository root holds the verbatim text of the GNU General Public License version 3 of 29 June 2007, with no added exceptions and no clauses pointing at another file. The GitHub programming interface reports GPL-3.0 for that repository. The client libraries follow a separate, permissive path: the typesense package at version 3.0.6 on npm declares Apache-2.0 and genuinely ships a LICENSE file with the Apache 2.0 text inside the published archive, while the typesense package at version 2.0.0 on PyPI states Apache 2.0 along with the matching OSI classifier.

One discrepancy does exist and it concerns binary distribution. The GitHub release carries no attached files, and the ready-made binary is downloaded from dl.typesense.org. The typesense-server-30.2-linux-amd64.tar.gz archive weighs about 133 MB and contains exactly two entries: the typesense-server executable and typesense-server.md5.txt with a checksum. There is no licence file in that archive at all. The GPL requires that a copy of the licence travels with the program you convey, so if you build your own container image or system package on top of that archive and hand it onward, add LICENSE.txt from the repository yourself.

Now the heart of it, meaning what the GPL implies for a search engine. Version three of the GPL is not the AGPL, and that difference settles most of the worry. Its obligations are triggered by conveying the program to another person, not by making it available over a network. If you run Typesense on your own server, your application queries it over HTTP, and users see only search results, you convey the program to nobody and owe nothing. The same holds when you have modified the engine for your own needs and keep those changes to yourself.

The obligations begin at distribution. If you sell a product installed at a customer site, ship an appliance with software loaded on it, or hand over a container image containing Typesense, you are conveying a program covered by the GPL. You must then make the engine's corresponding source, together with your changes to it, available to the recipient under the same licence, and include the licence text. Your own application code, which talks to the engine solely through an HTTP API, remains a separate work, because the boundary here is a network protocol rather than linking against a library. The Apache 2.0 client libraries carry nothing across either.

This describes the mechanism rather than offering legal advice, and with an install-at-the-customer model the topic is worth running past your legal team. The conclusion is nonetheless calm: for a typical team building a web application a GPL search engine changes nothing, while for a vendor of shipped software it changes a great deal. The Meilisearch core, by comparison, is MIT and imposes none of this in either scenario, while choosing AGPLv3 in Elasticsearch extends the same obligations to network availability.

Installation and the first index

The shortest route to a running instance goes through a container, and in production through a system package or the binary with a data directory.

Code
Bash
docker run -d --name typesense -p 8108:8108 \
  -v /var/lib/typesense:/data \
  typesense/typesense:30.2 \
  --data-dir /data \
  --api-key=$TYPESENSE_ADMIN_KEY \
  --enable-cors

curl "http://localhost:8108/health"

curl "http://localhost:8108/collections" \
  -X POST \
  -H "X-TYPESENSE-API-KEY: $TYPESENSE_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d @products-schema.json

A collection schema is ordinary JSON in which every field gets a type and optional flags.

Code
JSON
{
  "name": "products",
  "fields": [
    { "name": "title", "type": "string" },
    { "name": "brand", "type": "string", "facet": true },
    { "name": "categories", "type": "string[]", "facet": true },
    { "name": "price", "type": "float" },
    { "name": "in_stock", "type": "bool", "facet": true },
    { "name": "num_reviews", "type": "int32" }
  ],
  "default_sorting_field": "num_reviews"
}

Three details in that file decide whether you will be rebuilding the collection a month from now. The default_sorting_field must point at an int32 or float field and orders results whenever a query supplies no sort_by of its own, so it should express some measure of popularity. The sort flag defaults to on for numbers and off for other types, so sorting by a text field has to be declared explicitly. The infix flag allows matching a fragment inside a word and is off by default, because the documentation warns outright about its memory cost.

Documents are loaded in bulk as JSONL, one object per line. The import accepts an action parameter with the values create, upsert, update and emplace, and large datasets are split into batches of a few thousand lines.

Code
Bash
curl "http://localhost:8108/collections/products/documents/import?action=upsert" \
  -X POST \
  -H "X-TYPESENSE-API-KEY: $TYPESENSE_ADMIN_KEY" \
  --data-binary @products.jsonl

curl "http://localhost:8108/collections/products/documents/search\
?q=jacket&query_by=title,brand&filter_by=in_stock:true" \
  -H "X-TYPESENSE-API-KEY: $TYPESENSE_SEARCH_KEY"

Search, typos and vectors

A query from inside an application usually goes through a client library. Below is a JavaScript call with the parameters people set most often in practice.

Code
JavaScript
import Typesense from 'typesense'

const client = new Typesense.Client({
  nodes: [{ host: 'localhost', port: 8108, protocol: 'http' }],
  apiKey: process.env.TYPESENSE_SEARCH_KEY,
  connectionTimeoutSeconds: 2
})

const results = await client
  .collections('products')
  .documents()
  .search({
    q: 'wintr jacket',
    query_by: 'title,brand,categories',
    query_by_weights: '4,2,1',
    filter_by: 'in_stock:true && price:<500',
    facet_by: 'brand,categories',
    sort_by: '_text_match:desc,num_reviews:desc',
    num_typos: '2,1,0',
    exclude_fields: 'embedding',
    per_page: 20
  })

The order of fields in query_by matters, because it sets match priority, and query_by_weights expresses that priority as numbers instead of relying on order alone. The num_typos parameter takes a separate value per field, so above the title tolerates two typos, the brand one, and the categories none. Two further parameters tune behaviour on difficult queries: typo_tokens_threshold decides at what number of hits the engine reaches for the typo-tolerant version of the query at all, while drop_tokens_threshold allows dropping successive query words when the full set returns nothing. exclude_fields deserves a thought too, since an embedding vector field can weigh more in the response than the rest of the document.

Semantic search is configured in the schema rather than in the query. A float[] field with an embed section tells the engine to compute the embeddings itself during indexing.

Code
JSON
{
  "name": "products",
  "fields": [
    { "name": "title", "type": "string" },
    { "name": "description", "type": "string" },
    {
      "name": "embedding",
      "type": "float[]",
      "embed": {
        "from": ["title", "description"],
        "model_config": { "model_name": "ts/all-MiniLM-L12-v2" }
      }
    }
  ]
}

Models prefixed with ts/ come from the Typesense repository on Hugging Face and download automatically on first indexing. Embeddings are recomputed only when one of the fields listed in embed.from changes, so a stock level update does not trigger expensive recalculation. When you put text fields and the embedding field together into query_by, the engine performs a hybrid search and combines both lists with the formula rank_fusion_score = 0.7 * K + 0.3 * S, where K is the document's rank in the keyword results and S its rank in the semantic ones. The proportions are changed with the alpha parameter. If you compute embeddings on your own side, you omit the vector field from query_by and pass the ready vector through vector_query.

Clustering, replication and high availability

This is where Typesense pulls away from the simplest options. A cluster runs on the Raft algorithm, replicates the entire dataset to every node, and does so in the open version, with no commercial module and no change of licence.

Configuration comes down to a single file listing the nodes, pointed at by --nodes. Each entry takes the form <peering_address>:<peering_port>:<api_port>, and entries are separated by commas.

Code
Bash
# /etc/typesense/nodes
192.168.12.1:8107:8108,192.168.12.2:8107:8108,192.168.12.3:8107:8108
Code
Bash
typesense-server \
  --data-dir=/var/lib/typesense \
  --api-key=$TYPESENSE_ADMIN_KEY \
  --api-address=0.0.0.0 \
  --api-port=443 \
  --peering-address=192.168.12.1 \
  --peering-port=8107 \
  --nodes=/etc/typesense/nodes \
  --ssl-certificate=/etc/ssl/typesense.crt \
  --ssl-certificate-key=/etc/ssl/typesense.key

Several rules follow from the nature of Raft and from the documentation. A quorum needs a majority, so three nodes survive the failure of one and five nodes the failure of two, at the price of slightly higher write latency. Writes accepted by any node are forwarded internally to the leader, while reads are served by the node that received them, so adding nodes raises search throughput. Every node starts with the same admin key. The address in --peering-address should be private, because Raft traffic between nodes is unencrypted, whereas --api-address may be public and is the one serving clients.

Two further parameters earn their keep during failures. --snapshot-interval-seconds governs how often state snapshots are taken, the ones a joining node restores from, and --reset-peers-on-error lets a cluster rebuild its member list after losing quorum. On the client side the official libraries accept a list of nodes and health-check them themselves, and nearestNode routes traffic to the closest one, so a load balancer is not mandatory.

By comparison, in the open version of Meilisearch replication and sharding fall under separate licence terms rather than plain MIT. If you are after something simpler than Elasticsearch without giving up tolerance for a single machine failure along the way, that difference is what settles the choice.

Typesense Cloud, pricing and cloud-only features

The managed service sells a dedicated cluster rather than a plan with limits. The pricing page states outright that there is no cap on records or operations, and the hourly rate follows from the configuration: amount of memory, number of virtual cores, plus switches for a higher performance disk, GPU acceleration for computing embeddings, high availability and a search delivery network. There are 26 data centre locations to choose from.

The rates below were read off the calculator on 21 August 2026. The arithmetic holds up: the monthly figure is the hourly rate times 720 hours.

ConfigurationHourly rateMonthly figure from the page
0.5 GB RAM, 2 vCPUs with one burst hour per day0.03 USD21.60 USD
4 GB RAM, 2 vCPUs with four burst hours per day0.10 USD72.00 USD
4 GB RAM, the same configuration with high availability on three nodes0.33 USD237.60 USD
Outbound traffic0.09 USD per GBdepends on traffic

The third row deserves attention, because three nodes cost 3.3 times more than one rather than three times. The overhead is small, but it is better known than discovered while budgeting. Basic support is included, and prioritised plans are paid for separately.

There is one inconsistency in the messaging. The description meta tag on the pricing page promises a generous free tier, whereas the calculator itself holds no zero-cost option at all, the cheapest configuration being the 0.03 USD per hour mentioned above. If you are counting on a permanently free cluster, the way Supabase or the Qdrant cloud provide one, confirm it before opening an account, because the calculator page does not show it.

Some features exist only in the managed service, and the documentation marks them in its table of contents with a cloud note: the search delivery network, meaning a cluster spread across three or five regions with queries routed to the nearest one, team accounts, role-based access control in the admin dashboard, and single sign-on. The cloud also takes high availability off your hands and gives you one load-balanced endpoint, though the documentation notes that only clusters created after 16 June 2022 see such an endpoint.

Vendor lock-in here is moderate, because the same open binary runs underneath and data comes out through an ordinary document export. What you lose are the four features above, plus you rebuild yourself what the dashboard provided: backups, version upgrades and monitoring.

Typesense against the alternatives

FeatureTypesenseMeilisearchElasticsearchPostgreSQLQdrant
Engine licenceGPL-3.0MIT with BSL modulesAGPLv3, ELv2 or SSPLPostgreSQL licenceApache 2.0
Deploymentone binaryone binarya cluster on the Java virtual machinea database serverone process or container
Replication in the open versionyes, Raft from three nodeslimited by module termsyesyes, streaming replicationyes
Typos in the queryon by defaulton by defaultthrough a fuzziness parameterthrough a trigram extensionnot applicable
Vectorsyes, with automatic embeddingyes, hybrid modeyesthrough the pgvector extensionthe core of the product
Vendor cloudTypesense Cloud, hourly billingMeilisearch CloudElastic Cloudmany managed providersQdrant Cloud with a free plan

The choice comes down to a handful of questions. If the dataset is small, traffic is modest, and the data already sits in a relational database, start with full-text search in PostgreSQL and do not add another system to maintain. If you need fast typo-tolerant search with facets and a single machine suffices, Meilisearch and Typesense sit close together, differing in licence and in what the open version includes. If you want replication with no licence fees, Typesense beats Meilisearch. If you need aggregations, log analysis, many query types and a whole plugin ecosystem, neither of those two replaces Elasticsearch. And if the main job is vector similarity at scale with metadata filtering, reach for a vector database instead.

Common mistakes

The first is confusing the GPL with the AGPL in both directions. Teams give up on Typesense unnecessarily, fearing an obligation to open the source of their web application that the GPL simply does not impose. In the other direction, vendors of software installed at customer sites are sometimes surprised that handing over an image containing the engine triggers an obligation to supply the engine's source together with any modifications.

The second is redistributing the release archive without a licence file. The archive from dl.typesense.org holds only the binary and a checksum, so a container image of your own built on top of it needs the licence text from the repository added back in.

The third is underestimating memory. The index lives in RAM, so picking the cheapest configuration for a dataset that will double within six months ends in moving the cluster. Before choosing a size, add up the sizes of the fields you genuinely index, and remember that the infix flag raises that bill noticeably.

The fourth is an admin key in the browser. A key with full permissions can drop a collection, so generate a key scoped to search alone for the user interface, and for multi-tenant setups a key narrowed further by an embedded filter.

The fifth is a two-node cluster. Raft requires a majority, so two nodes survive the failure of neither and merely provide an illusion of redundancy. The minimum that changes anything is three.

The sixth is a public address in --peering-address. Raft traffic is unencrypted, so that address belongs on a private network, and what you expose outward is only --api-address with a certificate.

The seventh is a schema designed without a thought for facets and sorting. Adding a facet or sort flag to an existing field requires altering the collection and reindexing that field, which on a large dataset is a planned operation rather than one request slipped in between two deployments.

FAQ

Does the GPL force me to open the source of my application?

No, not if you merely run Typesense on your own server and query it through the API. Version three of the GPL ties obligations to conveying the program rather than to making it available over a network, so offering a service to users is not distribution. The obligation to supply the engine's source along with your changes appears only once you hand a binary to someone, for instance inside a product installed at a customer site.

How does Typesense differ from Meilisearch?

The feature range is similar: both have typo tolerance on by default, facets, filters and hybrid search, and both are a single binary. The differences are two and both are about licensing. Typesense is GPL-3.0 and offers Raft-based clustering in the open version. Meilisearch has an MIT core, a gentler licence when it comes to distribution, but replication and sharding there fall under separate terms.

Will Typesense replace Elasticsearch?

For searching a product catalogue, documentation or site content it usually will, at a noticeably lower maintenance cost. It will not replace it where complex aggregations, log analysis, stream processing and a plugin ecosystem matter. If you use Elasticsearch purely as a text search engine, migration is realistic; if you use it as a store of operational data, that is a different class of system.

How much memory does a cluster need?

As much as the index takes, plus headroom for growth and for operations. The starting point is the sum of the sizes of the fields you genuinely index rather than the size of whole documents, because fields stored without indexing cost less. The cloud calculator includes an assistant that takes the number of records and the average size of one record and proposes a starting configuration.

Does Typesense Cloud have a free plan?

The pricing calculator shows no zero-cost option, and the cheapest configuration with 0.5 GB of memory costs 0.03 USD per hour, which the page converts to 21.60 USD a month. The description meta tag on that same page nevertheless mentions a generous free tier, so we have two contradictory statements from one vendor, and it is worth confirming which holds before opening an account.

Can a cluster be moved from the cloud to my own server?

Yes, because the cloud runs the same open binary in the version you selected. Documents come out through the export endpoint, collection schemas download as JSON, and you recreate them on your own instance. What stays behind with the managed service is the search delivery network, team accounts, dashboard roles and single sign-on, while backups and upgrades become your job.

Documentation lives on the Typesense site, the cloud rates on the pricing page, and the source code in the GitHub repository.

Read next

We use cookies to enhance your experience on the site