Portable index across library, self-hosted, or SeekStorm Cloud.
Self-host for free, or let us run it.
Real-time, full-text and vector search for millions to billions of documents, with sub-millisecond latency at any scale — two lines of code to your first query.
Lexical + vector, one query.
Fast automatic correction.
Searchable the instant it's indexed.
Multi-field ordering, tie-breaking, and boosting.
Value and range facets.
Latin, Cyrillic, CJK, Arabic.
Turn any website into clean, structured, searchable JSON — thousands of pages per second, boilerplate stripped, structured data extracted automatically.
Polite, multi-threaded.
schema.org, Open Graph.
Definable, keeps results fresh.
SeekStorm combines lexical (BM25) and vector search natively — no separate database to sync, no re-ranking pipeline to duct-tape together.
Lexical + vector, one query, one index.
Plug SeekStorm into Claude, Cursor, or any MCP-compatible agent in minutes.
Documents are searchable the same millisecond they're indexed.
The same binary index moves with you — from an embedded library, to a self-hosted server, to fully managed cloud.
Embedded in your app, no server to run.
REST API, on your own infrastructure.
We run it, you don't.
A slow query isn't just slower — it's lost conversions and lost revenue. Search that's fast on average but spikes at the 99th percentile can still cost you the sale.
Why tail latency costs you customers →Because “instant” is a human-perception concept, not an engineering target.
Average latency isn't enough. Search infrastructure needs headroom for thousands of concurrent queries, complex queries, and traffic spikes.
Real-time systems, high-frequency applications, and AI agents can issue requests at machine speed — often many in parallel.
When search is one step in a larger application or agent workflow, every millisecond adds up.
No garbage collection pauses, no JVM tuning, no surprise latency spikes at the 99th percentile.
Architecture built to parallelize query execution as your index grows.
Built into the core architecture, not bolted on as a separate tokenizer step.
SymSpell, PruningRadixTrie, and a faster-than-Block-Max-WAND top-k union.
Lexical + vector, one query, one index.
MCP server, real-time indexing — search that keeps up with your agents.
Library ↔ server ↔ cloud — same binary index, every step. No lock-in.
The permissive alternative to Algolia, Elasticsearch, and Turbopuffer.
Free to self-host. Forever.
Same REST API underneath, idiomatic on top. Pick a client that fits your stack.
pip install seekstorm-client-pure-py
from seekstorm_client import SeekStorm, CreateIndexRequest, SearchRequestObject
client = SeekStorm(
base_url="http://127.0.0.1:80",
apikey_base64="YOUR_APIKEY_BASE64"
)
schema = [
{"field": "title", "field_type": "Text", "store": True, "index_lexical": True},
]
create_request = CreateIndexRequest(
index_name="demo_index",
schema=schema,
similarity="Bm25f",
tokenizer="UnicodeAlphanumeric",
stemmer="None",
document_compression="Snappy",
ngram_indexing=0,
)
index_id = client.create_index(create_request).index_id
client.index_document(index_id, {"title": "rust search"})
client.commit_index(index_id)
query = SearchRequestObject(query_string="rust search", offset=0, length=10)
result = client.query_index(index_id, query)
print(f"total hits: {result.count_total}")
client.close()
npm install seekstorm_client_ts
import { FieldType, SeekStormClient } from "seekstorm_client_ts";
const client = new SeekStormClient({
baseUrl: "http://127.0.0.1:80",
apiKey: "YOUR_APIKEY_BASE64",
});
const indexId = await client.createIndex({
index_name: "demo_index",
schema: [{field: "title", field_type: FieldType.Text, store: true, index_lexical: true}]
});
await client.indexDocument(indexId, { title: "rust search" });
await client.commitIndex(indexId);
const result = await client.search(indexId, { query: "rust search", length: 10 });
console.log(`total hits: ${result.count_total}`);
cargo add seekstorm_client_rs tokio serde_json
use seekstorm_client_rs::{RestClient, CreateIndexRequest, Document, SearchRequestObject};
use std::sync::LazyLock;
use std::error::Error;
pub static BASE_URL: &str = "http://127.0.0.1:80";
pub static API_KEY: &str = "YOUR_APIKEY_BASE64";
pub static CLIENT: LazyLock = LazyLock::new(|| RestClient::new());
#[tokio::main]
async fn main() -> Result<(), Box> {
let schema = serde_json::from_str(
r#"[{"field":"title","field_type":"Text","store":true,"index_lexical":true}]"#,
)?;
let create_index_request = CreateIndexRequest {
index_name: "demo_index".into(),
schema,
..Default::default()
};
let index_id = CLIENT
.create_index(BASE_URL, API_KEY, &create_index_request)
.await?
.index_id;
let document: Document = serde_json::from_str(r#"{"title":"rust search"}"#)?;
CLIENT.index_document(BASE_URL, API_KEY, index_id, &document).await?;
CLIENT.commit_index(BASE_URL, API_KEY, index_id).await?;
let search_request = SearchRequestObject {
query_string: "rust search".into(),
length: 10,
..Default::default()
};
let result = CLIENT.query_index(BASE_URL, API_KEY, index_id, search_request).await?;
println!("total hits: {}", result.count_total);
Ok(())
}
dotnet add package SeekStorm.Client
using SeekStorm.Client;
var client = new SeekStormClient(
baseUrl: "http://localhost:80",
apiKeyBase64: "YOUR_APIKEY_BASE64"
);
var createIndex = await client.CreateIndexAsync(new CreateIndexRequest
{
IndexName = "demo_index",
Schema = new List>
{
new()
{
["field"] = "title",
["field_type"] = "Text",
["store"] = true,
["index_lexical"] = true
}
}
});
await client.IndexDocumentAsync(createIndex.IndexId, new Dictionary
{
["title"] = "rust search"
});
await client.CommitIndexAsync(createIndex.IndexId);
var result = await client.QueryIndexAsync(createIndex.IndexId, new SearchRequestObject
{
QueryString = "rust search",
Length = 10
});
Console.WriteLine($"Total hits: {result.CountTotal}");
implementation 'com.seekstorm:seekstorm-client:1.0'
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.seekstorm.client.SeekStormClient;
import com.seekstorm.client.model.SearchRequest;
import com.seekstorm.client.model.SearchResponse;
ObjectMapper mapper = new ObjectMapper();
SeekStormClient client = SeekStormClient.builder()
.baseUrl("http://127.0.0.1:80")
.apiKey("YOUR_APIKEY_BASE64")
.build();
JsonNode createIndexRequest = mapper.createObjectNode()
.put("index_name", "demo")
.set("schema", mapper.createArrayNode()
.add(mapper.createObjectNode()
.put("field", "title")
.put("field_type", "Text")
.put("store", true)
.put("index_lexical", true)));
long indexId = client.createIndex(createIndexRequest);
JsonNode document = mapper.createObjectNode()
.put("title", "rust search");
client.indexDocument(String.valueOf(indexId), document);
client.commitIndex(String.valueOf(indexId));
SearchRequest request = SearchRequest.builder("rust search")
.length(10)
.build();
SearchResponse result = client.search(String.valueOf(indexId), request);
System.out.println("Total hits: " + result.countTotal());
go get github.com/seekstorm/seekstorm-go
import "github.com/seekstorm/seekstorm-go"
client := seekstorm.NewClient("http://localhost:80")
result := client.Search("my_index", "rust search")
SeekStorm's InstantSearch-compatible adapter means you can point your existing frontend at SeekStorm and change almost nothing else — or use it to build a fresh UI with Algolia's InstantSearch widget library, backed by SeekStorm's REST API.
Pay for what you use, split by resource — so you can see what's actually driving your bill, instead of one blended number.
Estimate your cost before deployment. Monitor usage in real time. Set a monthly spending cap. No surprise bills.
|
Monthly commitment
$20
|
0% off |
|
Documents
1M
|
$0.00 |
|
Document updates / month
100K
|
$0.00 |
|
Queries / month
100K
|
$0.00 |
|
Average results per query
10
|
$0.00 |
| Included | |
| $0.00 | |
| $0.00 | |
| $0.00 | |
| Estimated monthly cost | $0.00 |
Estimated cost — because your workload inputs are estimates. Not a plain sum: usage rows already reflect your commitment discount, and the total is the greater of that discounted usage cost and your commitment, plus any add-ons.
When your limit is reached, SeekStorm automatically throttles usage instead of continuing to incur charges.
Commit more, pay less. Set a spending limit. Full flexibility for everyone — no price-plan bundle constraints. Signing up commits to the rates and monthly minimum shown above.
We're happy to help with large projects — custom integrations, dedicated infrastructure, and tailored support.
Talk to us →SeekStorm is a permissive open-source alternative to Algolia, Elasticsearch, and Turbopuffer. Run the core engine yourself at no cost, or let us run it for you on SeekStorm Cloud.
What being open source actually changes — not a full feature comparison, just what follows directly from the license.
| SeekStorm | Elasticsearch | Algolia | Turbopuffer | |
|---|---|---|---|---|
| Open-source | ✓ Permissive (Apache 2.0) | ✓ Non-permissive (AGPL) | ✕ | ✕ |
| Self-host | ✓ Free forever | ✓ | ✕ | ✕ |
| Index portability | ✓ Library ↔ server ↔ cloud | ✕ | ✕ | ✕ |
While working hard to bring the best search to our customers, we are also committed to contributing to the open-source community.
SeekStorm: vector & lexical search - in-process library & multi-tenancy server, in Rust.
Fast spelling correction — powers SeekStorm's typo tolerance
Fast autocomplete — powers instant-as-you-type search
Word segmentation — powers search in compound and unspaced languages