AI & MCP

Semantic search on a site: when synonyms are enough

Embeddings earn their place when the query shares no words with the content. With a closed vocabulary a synonym table answers faster and costs nothing.

Key points

  • A synonym table covers a closed vocabulary with no external service and no network latency.
  • Embeddings cost in three places: generation, storage and the index.
  • 111,985 vectors at 1,536 dimensions in float32 take about 656 MiB before the index.

Semantic search earns its place when the query uses different words from the content; if the vocabulary is closed and predictable, a synonym table costs nothing and answers in under a second.

When a map is enough

A synonym map covers the vocabulary you already know: icons, categories, states. It needs no service, has no network latency and is reviewed by reading a file. The catch is that someone has to write it and keep it current.

QueryResultsBytesTime
delete296726378 ms
dashboard12739537 ms

These are single measurements taken from an HTTP client on 1 November 2026, one request per query: good for an order of magnitude, not for an average.

When vectors are needed

Embeddings are needed when the query is a sentence and the content does not contain those words. You pay in three places: generation, storage and the index.

The matrix is quick to size: 111,985 vectors at 1,536 dimensions in float32 take 688,035,840 bytes, about 656 MiB, before any index.

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE component_embedding (
  component_id text PRIMARY KEY,
  embedding vector(1536) NOT NULL
);

CREATE INDEX ON component_embedding
  USING hnsw (embedding vector_cosine_ops);

Hybrid, not religious

Search that works adds two signals: the exact filter on category and library, and similarity on the text. The filter shrinks the search space before the comparison, so results stay correct even when the vector is wrong.

The limitation

We have no quality measurement: recall and precision need a set of queries with expected answers, and this site has not published one. The pgvector 0.3.0 package on npm is small at 52,767 bytes, read on 1 November 2026, but the HNSW index lives in memory and has to be sized.

Where to continue

A keyboard palette on top of search is in a command menu with shadcn, the database choice in SQLite or Postgres, catalogue filters in faceted search. The records: 111,985 components, 12,808 icons, Aceternity UI.

Frequently asked questions

Does semantic search always improve results?

No. It improves natural-language queries and hurts exact ones, such as a product code or a component name. That is why it runs hybrid with an exact filter.

What does it cost to index 111,985 items?

It depends on the tokens per item. With text-embedding-3-small at $0.02 per million tokens, the cost is token count divided by a million, times $0.02. Storage is predictable: about 656 MiB in float32 at 1,536 dimensions.

Do I need a dedicated vector database?

Not at this scale. Postgres with pgvector, or SQLite with sqlite-vec, keep vectors next to the data and let you filter in the same query.

How many results should search return?

Ten is a fair starting point for a catalogue page, with cursor pagination after that. The real number depends on how many rows a person can judge before changing the query.

How do I measure whether search improved?

With a set of twenty or thirty real queries and the expected result written next to each, counting how many correct results appear in the first ten. Without that set every comparison is an impression.