SO

Sonic

Fast, lightweight schema-less search backend

Search Engines ★ 21.3k stars Medium setup MPL-2.0

Sonic is a fast, lightweight and schema-less search backend that can be used as a simpler, more efficient alternative to Elasticsearch. It is designed to ingest and query text with minimal resources.

Key features

  • Extremely low memory usage
  • Schema-less ingestion
  • Fast prefix and word search
  • Simple text protocol

Pros & cons

Strengths

  • Tiny resource footprint
  • Very fast for autocomplete

Trade-offs

  • No relevance scoring or filtering

Sonic replaces

Last reviewed Aug 26, 2026 · 859 words

Sonic returns identifiers, never documents. You push it text tagged with an object ID, it builds an index, and a query hands back the IDs whose text matched, with no ranking score, no filtering and no stored fields. That is the entire product. It runs in about 32 MB of RAM (the catalogue's minimum is the real-world number, not a floor), and once you accept the shape, it is the fastest and cheapest way to add search-as-you-type to an application that already keeps its data somewhere sensible.

IDs in, IDs out

The mental model is a phone index, not a database. Your app owns the documents in Postgres or SQLite; Sonic owns a map from words and prefixes to the IDs you told it about. Search asks Sonic for matching IDs, then your app fetches those rows and renders them. The catalogue's single con, "no relevance scoring or filtering," follows directly: Sonic does not know a title from a body, cannot restrict results to one user's records unless you put that scoping in the bucket name, and returns matches in an order that is not a relevance order.

The people who get burned by this are the ones who wanted Meilisearch and picked Sonic for the memory figure. Meilisearch and Typesense store documents, rank by typo-tolerant relevance, filter and facet, and cost hundreds of MB to a few GB of RAM to do it. The Elasticsearch versus Meilisearch comparison covers the document-store tier; Sonic is a tier below it on purpose.

A text protocol on port 1491, and 4 lines of compose

Sonic speaks a plain-text protocol over TCP, in the style of Redis, with 3 channel modes: ingest for writing, search for querying, and control for maintenance. It is written in Rust, ships as a Docker image and a single binary, and is configured by one TOML file.

services:
  sonic:
    image: valeriansaliou/sonic:latest
    ports:
      - "127.0.0.1:1491:1491"
    volumes:
      - ./sonic.cfg:/etc/sonic.cfg
      - ./sonic-store:/var/lib/sonic/store
    restart: unless-stopped

Copy the example config.cfg from the repository, set auth_password under [channel], and bind to localhost or your private network only; the protocol has a password and nothing else, no TLS and no per-user rights. A session looks like this:

START search SecretPassword
QUERY messages user:1a2b "invoice overdue" LIMIT(10)
SUGGEST messages user:1a2b "inv"
QUIT

messages is a collection, user:1a2b is a bucket inside it, and the reply to QUERY is a PENDING line followed by an EVENT QUERY line listing IDs. Putting the user ID in the bucket is how you get per-tenant scoping without a filter feature. Client libraries exist for Node, Python, Go, PHP, Rust and more, so you will not write the protocol by hand in production.

Ingest is your job forever

Sonic indexes what you push and only that. Every create, edit and delete in your application must be mirrored with a PUSH, a FLUSHO (drop one object) or a FLUSHB (drop a bucket), and there is no crawler, no database connector and no change-data-capture to do it for you. For an app you control, that is a 10-line hook on save. For indexing someone else's data store, it is a synchronisation job you own, and if it drifts, search silently returns stale IDs. Budget a periodic full reindex from the source of truth, which is cheap because ingestion is fast and the index is small.

Sonic detects the language of pushed text and applies stemming and stop words for it, so "invoices" matches "invoice" without configuration. Prefix search, which powers SUGGEST, is what makes it excellent for type-ahead: results arrive in low single-digit milliseconds on a small box.

Where it wins and where it cannot compete

It wins for autocomplete boxes, "jump to" pickers, message search inside a chat product (it was built for one) and any search over records your app already sorts and filters by itself. It also wins on hardware: a Raspberry Pi or the smallest VPS runs it beside the main app without noticing. It cannot compete where users expect the search box to know what is relevant: an e-commerce catalogue, a documentation site, a knowledge base with long articles. For those, the ranking and faceting in Meilisearch or Typesense is the product, and anyone leaving Algolia is looking for that tier, not this one.

What I'd do

Use Sonic when you are writing the application, you already have a database that answers "give me these rows," and what you need is fast prefix and word matching over short text for a few hundred MB of index or less. Run it on localhost next to the app, put the tenant ID in the bucket, wire PUSH and FLUSHO into your save and delete paths, and schedule a weekly full reindex. If the words "relevance," "filter" or "facet" appear in your requirements, take Meilisearch and accept the memory bill. The search category has both tiers laid out.

Compare Sonic

28 head-to-head comparisons.

Similar search engines apps