Typesense is an open-source, in-memory search engine replacing Searchspring and Algolia with typo-tolerant sub-50ms search and dynamic runtime sorting.
Typesense was built from scratch in C++ to hold search indices in memory while persisting JSON documents with RocksDB. Pairing an Adaptive Radix Tree with typo tolerance, the engine serves queries with sub-50-millisecond response times. Teams deploy it as a single binary or container to power instant search without JVM overhead.
Searchspring operates as a hosted service for e-commerce merchandising, routing queries over the internet to managed cloud clusters. That architecture introduces wide-area latency and recurring fees scaled by SKU counts and search volume. Typesense replaces that remote loop with an in-memory search daemon running inside your private network. Colocating search with application servers eliminates network hops, maintains sub-50-millisecond response times, and keeps catalog traffic private without third-party API rate limits.
The divide centers on architectural control and resource efficiency. Searchspring pairs closed ranking algorithms with visual merchandising dashboards, but conceals infrastructure controls. Typesense gives engineers programmatic control over field weights, typo tolerance, dynamic runtime sorting, and vector embeddings in a single collection. While Searchspring and Algolia often require separate replica indices for each sort order, Typesense evaluates sorting dynamically at query time from one index. In return, teams manage their own infrastructure, provisioning sufficient RAM for active indexes and operating internal Raft nodes.
Typesense vs Searchspring — which fits an e-commerce catalog? Searchspring suits retail teams needing hosted visual merchandising dashboards and automated campaign tooling out of the box. Typesense fits engineering teams wanting fast in-memory search, typo tolerance, and programmatic curation on private infrastructure without recurring search fees.
Does Typesense require all search data to fit in RAM? Yes. While raw document records are persisted on disk via RocksDB, all searchable tokens, facet data, and Adaptive Radix Tree structures live in memory, making sufficient RAM sizing essential.
Is Typesense free for commercial use? Yes. The server is open-source under the GPL-3.0 license with no document limits or feature paywalls, accompanied by permissively licensed official client SDKs for application code.
Typesense is a practical search engine for teams that prioritize predictable sub-50-millisecond query latency and can manage their own containerized nodes rather than paying recurring SaaS bills. With commits pushed as recently as September 2026 and an active issue tracker, the project maintains strong development momentum. A GPL-3.0 license governs the server daemon—requiring server-level modifications to remain open while allowing proprietary applications to query the HTTP API freely—making it a dependable choice provided your team provisions adequate RAM.
We started this exact setup from scratch in a clean Linux machine on Nov 1, 2026 and checked it through Typesense's own API: every check passed. Recipes are re-checked regularly and removed if they stop working.
mkdir -p typesense && cd typesense
curl -fsSL https://open-source.store/tools/typesense/compose.yml -o compose.ymlcat > .env <<EOF
TYPESENSE_API_KEY=$(openssl rand -hex 16)
EOFTYPESENSE_API_KEY — Admin API key for authenticating Typesense requests. Generated above; keep it secret.docker compose up -dservices:
typesense:
image: typesense/typesense:30.2
restart: on-failure
ports:
- "127.0.0.1:8108:8108"
environment:
TYPESENSE_API_KEY: ${TYPESENSE_API_KEY}
TYPESENSE_DATA_DIR: /data
TYPESENSE_ENABLE_CORS: "true"
volumes:
- typesense-data:/data
command: '--data-dir /data --api-key=${TYPESENSE_API_KEY} --enable-cors'
volumes:
typesense-data:
Free IDE for Java, Kotlin, Go, TypeScript and Python. Built on IntelliJ Community, fully open source, 300+ plugins.
Show that Typesense is listed as an open-source alternative. Paste into your README:
Ubuntu 24.04 · Apple container, Docker 29.1.3, Compose 2.40.3+ds1-0ubuntu1~24.04.1. Images pulled in 30 s: typesense/typesense:30.2.
Based on the upstream setup. Official Docker Compose setup from Typesense documentation. Pinned image to 30.2, data directory mounted to named volume, API key configured via .env, and bound to 127.0.0.1 per step 4a.
typesense-1 | 2026-11-01T15:15:47.817685000Z W20261101 15:15:47.817386 116 protobuf_file.cpp:91] open file failed, path: /data/state/log/log_meta: FILE_ERROR_NOT_FOUND typesense-1 | 2026-11-01T15:15:47.817748125Z W20261101 15:15:47.817696 116 log.cpp:698] /data/state/log is empty typesense-1 | 2026-11-01T15:15:47.818386166Z W20261101 15:15:47.818285 116 protobuf_file.cpp:91] open file failed, path: /data/state/meta/raft_meta: FILE_ERROR_NOT_FOUND typesense-1 | 2026-11-01T15:15:47.818417000Z I20261101 15:15:47.782727 1 typesense_server_utils.cpp:480] Starting Typesense 30.2 typesense-1 | 2026-11-01T15:15:47.818419208Z I20261101 15:15:47.782742 1 typesense_server_utils.cpp:483] Typesense is using jemalloc. typesense-1 | 2026-11-01T15:15:47.818419916Z I20261101 15:15:47.782827 1 typesense_server_utils.cpp:550] Thread pool size: 16 typesense-1 | 2026-11-01T15:15:47.818420541Z I20261101 15:15:47.784022 1 store.cpp:39] Initializing DB by opening state dir: /data/db typesense-1 | 2026-11-01T15:15:47.818421083Z I20261101 15:15:47.792183 1 store.cpp:39] Initializing DB by opening state dir: /data/meta typesense-1 | 2026-11-01T15:15:47.818421666Z I20261101 15:15:47.798033 1 ratelimit_manager.cpp:546] Loaded 0 rate limit rules. typesense-1 | 2026-11-01T15:15:47.818422208Z I20261101 15:15:47.798038 1 ratelimit_manager.cpp:547] Loaded 0 rate limit bans. typesense-1 | 2026-11-01T15:15:47.818422791Z I20261101 15:15:47.798175 1 typesense_server_utils.cpp:664] Loaded 0 natural language search model(s). typesense-1 | 2026-11-01T15:15:47.818424458Z I20261101 15:15:47.798194 1 typesense_server_utils.cpp:736] Starting API service... typesense-1 | 2026-11-01T15:15:47.818425083Z I20261101 15:15:47.798250 116 typesense_server_utils.cpp:372] Since no --nodes argument is provided, starting a single node Typesense cluster. typesense-1 | 2026-11-01T15:15:47.818425708Z I20261101 15:15:47.798343 1 http_server.cpp:243] Typesense has started listening on port 8108 typesense-1 | 2026-11-01T15:15:47.818426250Z I20261101 15:15:47.798735 117 batched_indexer.cpp:196] Starting batch indexer with 16 threads. typesense-1 | 2026-11-01T15:15:47.818426833Z I20261101 15:15:47.798982 117 batched_indexer.cpp:201] BatchedIndexer skip_index: -9999 typesense-1 | 2026-11-01T15:15:47.818427375Z I20261101 15:15:47.799010 119 typesense_server_utils.cpp:679] Conversation garbage collector thread started. typesense-1 | 2026-11-01T15:15:47.818427916Z I20261101 15:15:47.799263 147 batched_indexer.cpp:353] Starting reference sequence thread. typesense-1 | 2026-11-01T15:15:47.818428500Z I20261101 15:15:47.801391 116 server.cpp:1181] Server[braft::RaftStatImpl+braft::FileServiceImpl+braft::RaftServiceImpl+braft::CliServiceImpl] is serving on port=8107. typesense-1 | 2026-11-01T15:15:47.818429125Z I20261101 15:15:47.801397 116 server.cpp:1184] Check out http://d250913ab0c4:8107 in web browser. typesense-1 | 2026-11-01T15:15:47.818429708Z I20261101 15:15:47.801486 116 raft_server.cpp:80] Nodes configuration: 172.18.0.2:8107:8108 typesense-1 | 2026-11-01T15:15:47.818430250Z I20261101 15:15:47.801497 116 raft_server.cpp:123] Snapshot does not exist. We will remove db dir and init db fresh. typesense-1 | 2026-11-01T15:15:47.818430833Z I20261101 15:15:47.801651 116 store.cpp:245] rm /data/db success typesense-1 | 2026-11-01T15:15:47.818431500Z I20261101 15:15:47.801713 116 store.cpp:39] Initializing DB by opening state dir: /data/db typesense-1 | 2026-11-01T15:15:47.818432083Z I20261101 15:15:47.816761 116 store.cpp:269] DB open success! typesense-1 | 2026-11-01T15:15:47.818436625Z I20261101 15:15:47.816768 116 raft_server.cpp:665] Loading collections from disk... typesense-1 | 2026-11-01T15:15:47.818437666Z I20261101 15:15:47.816772 116 collection_manager.cpp:426] CollectionManager::load() typesense-1 | 2026-11-01T15:15:47.818438208Z I20261101 15:15:47.816787 116 auth_manager.cpp:35] Indexing 0 API key(s) found on disk. typesense-1 | 2026-11-01T15:15:47.818438750Z I20261101 15:15:47.816793 116 collection_manager.cpp:462] Loading upto 8 collections in parallel, 1000 documents at a time. typesense-1 | 2026-11-01T15:15:47.818439333Z I20261101 15:15:47.816797 116 collection_manager.cpp:471] Found 0 collection(s) on disk. typesense-1 | 2026-11-01T15:15:47.818439875Z I20261101 15:15:47.816927 116 collection_manager.cpp:628] Loaded 0 collection(s). typesense-1 | 2026-11-01T15:15:47.818440375Z I20261101 15:15:47.816929 116 collection_manager.cpp:629] Found 0 analytics config(s). typesense-1 | 2026-11-01T15:15:47.818440916Z I20261101 15:15:47.816931 116 collection_manager.cpp:634] Loaded 0 analytics config(s). typesense-1 | 2026-11-01T15:15:47.818441416Z I20261101 15:15:47.816931 116 collection_manager.cpp:641] Found 0 old analytics config(s) on disk. typesense-1 | 2026-11-01T15:15:47.818442000Z I20261101 15:15:47.816933 116 collection_manager.cpp:652] Restored 0 old analytics config(s). from 0 old analytics config(s) on disk. typesense-1 | 2026-11-01T15:15:47.818442625Z I20261101 15:15:47.816934 116 collection_manager.cpp:653] Removing restored old analytics config(s) from disk. typesense-1 | 2026-11-01T15:15:47.818443166Z I20261101 15:15:47.817023 116 raft_server.cpp:672] Finished loading collections from disk. typesense-1 | 2026-11-01T15:15:47.818443708Z I20261101 15:15:47.817028 116 raft_server.cpp:683] Loaded 0 conversation model(s). typesense-1 | 2026-11-01T15:15:47.818444208Z I20261101 15:15:47.817029 116 raft_server.cpp:687] Initializing batched indexer from snapshot state... typesense-1 | 2026-11-01T15:15:47.818444750Z I20261101 15:15:47.817032 116 raft_server.cpp:700] Loaded 0 personalization model(s). typesense-1 | 2026-11-01T15:15:47.818445291Z I20261101 15:15:47.817374 116 log.cpp:690] Use murmurhash32 as the checksum type of appending entries typesense-1 | 2026-11-01T15:15:47.818445833Z I20261101 15:15:47.818145 116 log.cpp:1150] log save_meta /data/state/log/log_meta first_log_index: 1 time: 434 typesense-1 | 2026-11-01T15:15:47.818446416Z I20261101 15:15:47.818298 116 raft_meta.cpp:521] Loaded single stable meta, path /data/state/meta term 1 votedfor 0.0.0.0:0:0 time: 8 typesense-1 | 2026-11-01T15:15:47.818997708Z W20261101 15:15:47.818909 116 controller.cpp:1550] SIGINT was installed with 1 typesense-1 | 2026-11-01T15:15:47.819000958Z W20261101 15:15:47.818933 116 node.cpp:843] [default_group:172.18.0.2:8107:8108 ] Refusing concurrent configuration changing typesense-1 | 2026-11-01T15:15:47.819001625Z E20261101 15:15:47.818940 116 raft_server.cpp:815] Node not ready yet (known_applied_index is 0). typesense-1 | 2026-11-01T15:15:47.819002208Z E20261101 15:15:47.818975 122 raft_server.h:62] Peer refresh failed, error: Doing another configuration change