Distributed Search logo

Distributed Search

Organization
proyecto26
distributed-search

This skill should be used when the user designs a "search system", needs "full-text search", asks about an "inverted index", "Elasticsearch / OpenSearch", "relevance ranking" (TF-IDF/BM25), "search autocomplete / typeahead", an "indexing pipeline", or "faceted search". It gives the crawl/index/search architecture, index sharding and replication, ranking, and near-real-time indexing. Use it whenever users must query text by relevance rather than fetch rows by key, even if they don't say "search engine".

Overview

Publisherproyecto26
Repositorysystem-design-skills
Skill namedistributed-search
Stars
117
Forks
14
Bundled files
5
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 5 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by proyecto26 on GitHub. Read the source before you install it.

Installation

Install the Distributed Search AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/proyecto26/system-design-skills/tree/main/skills/distributed-search
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/proyecto26/system-design-skills.git /tmp/system-design-skills
mkdir -p .claude/skills
cp -r /tmp/system-design-skills/skills/distributed-search .claude/skills/distributed-search
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Distributed Search in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Distributed Search on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Distributed Search is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Distributed search

Find the documents that best match a free-text query, ranked by relevance, fast, across more data than one machine holds. Getting it wrong means either slow LIKE '%term%' scans that melt the primary database, or a search box that returns the wrong results and erodes user trust — both are silent until traffic or corpus size exposes them.

When to reach for this

Users type words and expect ranked, relevant matches — not exact-key lookups. The corpus is text-heavy (documents, products, logs, messages), queries are ad-hoc (any term, any combination), and results need ranking, highlighting, facets, or typeahead. Reach for it when a WHERE col LIKE or full-table scan is already the read bottleneck, or when you need fuzzy/partial matching a B-tree index cannot serve.

When NOT to

The access pattern is fetch-by-known-key or a fixed filter — a primary database index serves that far more cheaply and consistently; keep it in data-storage. The corpus is tiny (thousands of rows): an in-process filter or the database's built-in full-text index is enough — a separate search cluster is pure operational overhead (YAGNI). Search is a derived, eventually-consistent copy of your data; never make it the system of record.

Clarify first

  • Corpus size and growth — document count, average doc size, total index bytes? (→ back-of-the-envelope) This decides shard count.
  • Query QPS and shape — read-heavy? term queries, phrase, fuzzy, facets, autocomplete? Latency target (p99)?
  • Indexing freshness — must a new/edited doc be searchable in seconds (near-real-time) or is minutes/hours of lag fine?
  • Relevance bar — is exact term-match enough, or do users expect "best" results (ranking, synonyms, typo tolerance)?
  • Write rate — how many docs/sec change? This sizes the indexing pipeline.

The options

The pipeline (almost always present): a source emits document changes → an indexing pipeline transforms/analyzes them → the inverted index stores term→document postings → the query path matches and ranks. For a crawl-based system (web search), prepend crawl → parse → dedupe; that crawler is its own subsystem feeding the same pipeline.

Index build mode

  • Batch / bulk reindex: rebuild the whole index periodically. Use when the corpus changes slowly or freshness in hours is acceptable.
  • Near-real-time (incremental): apply changes continuously so docs are searchable in seconds. Use when users expect to find what they just wrote.

Ranking model

  • Boolean / filter only: match, no scoring. Use for exact filtering (tags, facets) where order doesn't matter.
  • TF-IDF / BM25 (lexical): score by term frequency and rarity. The default full-text relevance model; cheap and explainable.
  • Hybrid (lexical + signals): blend BM25 with popularity, recency, or business boosts. Use when "best" means more than word overlap.

Autocomplete

  • Prefix trie / FST in memory: sub-millisecond typeahead from a prefix. Use for suggestion-as-you-type.
  • Edge-n-gram index: prefix matching inside the main index. Use when suggestions must also respect filters/relevance, at higher cost.

Distribution: split the index into shards (each a self-contained inverted index over a doc subset) for capacity, and replicas per shard for read throughput and fault tolerance. Sharding theory lives in data-storage.

Trade-offs

OptionWhat it solvesWhat it worsensChange it when
Batch reindexSimple, atomic swap, no live-write complexityStale until next build; full rebuild is costlyUsers need fresh results → near-real-time
Near-real-timeSeconds-fresh; no full rebuildSegment churn, merge load, refresh cost on writesWrite rate or merge cost overwhelms nodes → batch/larger refresh interval
Boolean/filterCheapest; deterministicNo notion of "best" resultUsers judge result quality → add BM25
BM25Good relevance, explainable, cheapIgnores popularity/recency/intentWord-overlap isn't enough → hybrid signals
Hybrid signalsMatches business/user intentComplex, harder to debug, needs tuning dataTuning cost exceeds value → fall back to BM25
Prefix trie/FSTFastest typeaheadSeparate structure to build/refresh; ignores filtersSuggestions need filters/relevance → edge-n-gram
More shardsParallelism, fits big corpusPer-query fan-out + merge overhead; tiny shards waste resourcesFan-out latency dominates → fewer, larger shards
More replicasRead QPS + HAMore RAM/disk; replication lag on writesWrite amplification hurts → fewer replicas

Behavior under stress

Search amplifies trouble through fan-out and derived-data lag.

  • Query fan-out tail latency: every query hits all shards; the slowest shard sets the response time. One hot or GC-paused shard drags every query. Mitigate: size shards evenly, add replicas, cap result depth, use timeouts + partial results.
  • Indexing vs query contention: a write/merge surge (bulk import, reindex) steals CPU and I/O from queries, spiking latency. Mitigate: throttle bulk indexing, schedule big merges off-peak, isolate index vs query node roles.
  • Hot shard / skew: an uneven shard key concentrates docs or popular terms on one node. Mitigate: hash-route documents; reroute or split the hot shard.
  • Deep pagination: from=100000 forces every shard to sort huge windows. Mitigate: cursor/search_after, cap page depth.
  • Pipeline backlog: if the source produces changes faster than the indexer consumes, freshness lag grows unbounded. Mitigate: backpressure and a durable buffer (→ messaging-streaming); monitor lag, not just throughput.
  • Cold cache after restart: filesystem/page cache is empty, so latency spikes until it warms. Mitigate: warm critical queries; ramp traffic.

Monitor: per-shard p99 query latency, indexing lag (source→searchable), segment/merge count, heap/GC, shard balance, and rejected/queued requests.

How to apply

  1. Clarify the inputs — pin corpus size, query QPS and shape, freshness target, and the relevance bar (see Clarify first). If a DB index or built-in full-text serves the access pattern, stop — you don't need a search cluster.
  2. Pick from the trade-off table — choose a build mode (freshness), a ranking model (relevance bar), and whether autocomplete needs its own structure.
  3. Set the key knobs — shard count (from index bytes ÷ target shard size), replica count (from read QPS + HA), the analyzer/tokenizer (language, stemming, synonyms), and the refresh interval (freshness vs write cost).
  4. Stress-test the choice — walk Behavior under stress (fan-out tail, indexing contention, hot shard, deep pagination, pipeline backlog) and confirm a mitigation for each one the traffic profile can trigger.
  5. Size it with numbers — confirm shards fit the corpus and per-shard size stays in a healthy range, replicas cover peak QPS, and indexing throughput keeps lag inside the freshness budget (→ Numbers that matter).
  6. Pick a provider — default to the generic recipe; open a provider file only if the user named a cloud (see Choosing a provider).
  7. Show the trade-off in the answer — give a Decision | Solves | Worsens | Change it when… table with one row per choice you made here (e.g. the option, its store, its failure policy); the last column is a concrete trigger (a number or observable signal). Then name what breaks first.

Dos and don'ts

Do

  • Treat the index as a derived, rebuildable copy — keep the system of record in data-storage and be able to fully reindex from it.
  • Size shards before launch (corpus ÷ target shard size); aim for even, not tiny, shards to bound fan-out cost.
  • Feed the indexing pipeline through a durable buffer so a write surge can't outrun the indexer or lose changes.
  • Start ranking with BM25; add popularity/recency signals only when word-overlap demonstrably misses intent.
  • Monitor indexing lag separately from query latency — freshness fails silently.

Don't

  • Don't use a search engine as your primary store or for transactional writes.
  • Don't reach for a separate cluster when a DB full-text index or in-process filter covers a small corpus (YAGNI).
  • Don't allow deep from/offset pagination; use cursors instead.
  • Don't over-shard — many tiny shards add fan-out and merge overhead without benefit.
  • Don't run heavy bulk reindex unthrottled against a cluster serving live queries.

Numbers that matter

The quantities that drive the design: total index bytes (corpus × per-doc overhead, then ÷ target shard size to get shard count), read QPS × fan-out (each query touches every shard) for replica sizing, and indexing throughput vs change rate to keep freshness lag inside budget. A single shard performs well within a bounded size range; past it, split. Use back-of-the-envelope for the latency, QPS, and storage figures — don't restate them here.

Interface sketch

The contracts are the document, the query, and the postings. A document is a typed record with analyzed fields, e.g. { "id": "p123", "title": "...", "body": "...", "tags": ["a","b"], "price": 9.99 }. A query names fields, match type, filters, sort, and pagination cursor, e.g. q="wireless earbuds", fields=[title^2, body], filter={tag:audio}, sort=_score, search_after=<cursor>. The inverted index maps each term → posting list of (doc_id, term_freq, positions); ranking reads these to compute BM25. Decide the analyzer (tokenizer, lowercasing, stemming, synonyms) up front — it is part of the contract and changing it requires a reindex.

Choosing a provider

Default to the generic recipe above (Elasticsearch/OpenSearch, Lucene, Solr, self-hosted). If the user names a cloud, read references/providers/<provider>.md for the managed-service mapping, quotas/limits, and provider-specific trade-offs. If no file exists for that provider, the generic recipe is the answer.

Diagram

To visualize the source → indexing pipeline → inverted index (sharded + replicated) → query/rank path, or the crawl→parse→dedupe front end, use the in-plugin architecture-diagram skill — show the indexing path and the query fan-out as distinct flows, with replicas behind each shard.

Related building blocks

  • data-storage — alternative to a DB LIKE/full-table scan for text search; search owns the inverted index, while sharding/partitioning and replication theory live there — name and link, don't re-teach.
  • messaging-streaming — depends on this for the index-update pipeline: a durable buffer carries document changes to the indexer and absorbs write surges (delivery, ordering, backpressure are owned there).
  • caching — pairs with this to cache hot/repeated queries and reduce fan-out load (stampede, hot-key, eviction handling owned there).
  • back-of-the-envelope — feeds into this skill: corpus bytes, QPS, and freshness numbers size the shards, replicas, and pipeline.
  • system-design — owned-concept lives in the orchestrator: the reasoning loop, the trade-off method, and the ten failure modes.

References

  • references/deep-dive.md — inverted-index internals (postings, segments, merges), the crawl/index/search pipeline, BM25 scoring, near-real-time refresh, autocomplete (trie/FST/n-gram), shard routing and replica reads. Read when designing the search layer in detail.
  • references/providers/{generic,aws,azure,gcp}.md — service mappings, limits, and pitfalls per environment.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Distributed Search AI skill do?

This skill should be used when the user designs a "search system", needs "full-text search", asks about an "inverted index", "Elasticsearch / OpenSearch", "relevance ranking" (TF-IDF/BM25), "search autocomplete / typeahead", an "indexing pipeline", or "faceted search". It gives the crawl/index/search architecture, index sharding and replication, ranking, and near-real-time indexing. Use it whenever users must query text by relevance rather than fetch rows by key, even if they don't say "search engine".

Why use Distributed Search on TypingMind?

Because you install it once and use it with any model. Distributed Search is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Distributed Search in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/proyecto26/system-design-skills/tree/main/skills/distributed-search. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Distributed Search?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Distributed Search?

As many as you like. As long as a model supports skills, you can use Distributed Search with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Distributed Search AI skill free?

Yes. It is published on GitHub by proyecto26 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇