← Back to projects

02 / Distributed systems · Full stack

Distributed Search Typeahead System

A full-stack distributed typeahead system built to study Redis routing, consistent hashing, targeted cache invalidation, batched event writes, ranking, and graceful database fallback under partial failure.

Role

Student project · repository owner

Status

Local systems project · source available · no public deployment

Main technologies
  • Redis
  • Consistent hashing
  • Cache invalidation
  • Batching
  • SQLite fallback
  • Spring Boot
Architecture illustrationDistributed Search Typeahead System
Implemented read path: a debounced React query reaches Spring Boot, checks the responsible Redis node, falls back to SQLite on a miss or cache failure, and returns ranked suggestions.

The problem

Typeahead has to respond on every few keystrokes while ranking suggestions from historical and recent activity. Writing every search event immediately creates unnecessary storage pressure.

Caching reduces read cost, but the design must decide where keys live, what to invalidate after writes, and what happens when a cache node cannot respond.

The solution

A Spring Boot service queries a 120,000-row local SQLite dataset, aggregates search events in memory, writes them in batches, and supports overall and recency-weighted trending ranking.

Suggestion keys route across three standalone Redis nodes using SHA-256 consistent hashing with virtual nodes. Reads fall back to SQLite when Redis is unavailable.

01

Use direct JDBC over SQLite

The data layer stays explicit and local for the assignment: ranking queries, transactions, and schema behavior are visible without an ORM or cloud dependency.

02

Route keys with consistent hashing

SHA-256 and virtual nodes distribute cache keys across three Redis instances while limiting remapping when the configured ring changes.

03

Invalidate only affected prefixes

After a successful batch commit, overall and trending prefix keys plus global trending are invalidated. TTL remains the recovery mechanism if invalidation fails.

Technical challenges

  1. Combining historical and recent candidates while preserving deterministic tie ordering.
  2. Reducing logical write volume without losing accepted events during normal shutdown.
  3. Keeping cache failures from becoming API failures while still reporting the result source for inspection.

Testing and reliability

  1. Redis connection failures and timeouts are treated as cache misses and fall back to SQLite.
  2. Batch writes run in one SQLite transaction and invalidation happens only after a successful commit.
  3. The repository documents backend tests, frontend component tests, CI, build checks, and deterministic demo scripts.
  4. The React UI handles debounce, stale-request cancellation, keyboard navigation, loading, error, and empty states.

04 / Current limitations

What the project does not claim.

  • Invalidation is process-local; multiple API instances would require a shared invalidation channel.
  • Accepted events that have not yet flushed can be lost on a hard process crash.
  • The deterministic local dataset and ranking are educational; the project does not implement machine-learned ranking or cloud deployment.

05 / Next improvements

What I would build next.

  • Move accepted events to a durable stream or log before batching.
  • Add a distributed invalidation channel and observable cache-node health.
  • Benchmark repeatable p50/p95 behavior under controlled load before making latency claims.