Skip to main content

search-module

# Search & Discovery Module

The high-performance, sub-50ms RAM-based discovery engine powering typo-tolerant and faceted searches.

Typesense MongoDB TypeScript BullMQ

1. Executive Summary & Architecture

The Search Module (src/modules/search/) implements a Dual‑Database Architecture:

  • MongoDB – primary source of truth for ACID transactions, financial records, and polymorphic data.
  • Typesense – a C++ based, purely in‑memory (RAM) search engine used for typo‑tolerant, faceted, sub‑50ms searches.

The module exposes a public GET /api/v1/search endpoint that queries Typesense directly, bypassing MongoDB for read‑heavy discovery operations.

Key benefits:

  • Typo tolerancenum_typos: 2 allows two typos per word.
  • Faceted filtering – returns counts for itemType and mainCategory for UI refinement.
  • RAM performance – Typesense keeps the entire index in memory, delivering consistent low latency.

2. Search Request Flow (Sequence Diagram)

Steps:

  1. Rate limitingstandardLimiter (100 requests per 15 min per IP) protects the RAM cluster.
  2. Zod validationSearchQuerySchema coerces page/limit/price to numbers, caps limit at 100, and defaults q to *.
  3. Typesense querySearchService.executeSearch builds the filter string and executes the search.
  4. Response – Raw results are wrapped in ApiResponse for consistency.

3. Eventual Consistency Synchronisation (Product → Typesense)

To keep Typesense aligned with MongoDB without slowing down admin CRUD, the ProductService uses a fire‑and‑forget eventual consistency pipeline with a Dead Letter Queue (DLQ).

Key points:

  • The sync is non‑blocking – MongoDB transaction succeeds even if Typesense is temporarily unreachable.
  • Failed syncs are pushed to a BullMQ dead‑letter queue with 10 attempts and exponential backoff (starting at 5 seconds).
  • The payload is stripped of heavy BSON data (e.g., nested variant objects) and images are set to index: false to preserve RAM.

4. Query Payload Firewall (Zod)

SearchQuerySchema (defined in search.dto.ts) acts as a strict gateway:

FieldTypeValidationDefaultNotes
qstring"*"Wildcard returns everything if empty.
pagenumberz.coerce.number().int().min(1)1Auto‑coerced from string.
limitnumberz.coerce.number().int().min(1).max(100)20Hard cap of 100 prevents memory exhaustion.
itemTypestringoptionalFacet filter (exact match).
mainCategorystringoptionalFacet filter.
minPrice / maxPricenumberz.coerce.number().min(0)Price range filter.
sortByenum"basePrice:asc", "basePrice:desc", "createdAt:desc"Strictly controlled to prevent injection.

Security: Zod coercion and caps block malicious payloads like limit=999999 or page=-1.


5. Typesense Search Configuration

ParameterValueDescription
query_byname,description,tags,skuFields indexed for text search.
num_typos2Allows up to two typos per word.
typo_tokens_threshold1Minimum word length for typo correction.
facet_byitemType, mainCategoryReturns counts for faceted filtering.
per_pagelimitCapped at 100.
filter_bydynamically builtitemType:=[BANGLE] && basePrice:>=100 etc.

Strict SDK Typings: The service uses ITypesenseProductDoc generic to avoid object defaults, satisfying exactOptionalPropertyTypes and preventing CodeQL “Type Confusion” alerts.


6. Security & Rate Limiting

ThreatMitigation
DoS / scraping attacksstandardLimiter (100 requests / 15 min per IP) applied to /search.
Memory exhaustionlimit capped at 100 in Zod schema.
NoSQL / injectionZod type coercion + strict filter building; Typesense uses its own safe parser.
Typosquatting / bad queriesnum_typos: 2 ensures usability while limiting resource use.

FilePurpose
src/modules/search/search.controller.tsHTTP layer, calls service, wraps response.
src/modules/search/search.service.tsBuilds Typesense query, executes, returns raw results.
src/modules/search/search.routes.tsRoute definition with standardLimiter and validate.
src/modules/search/dtos/search.dto.tsZod schema for query validation.
src/config/typesense.tsTypesense client initialisation and schema management.
src/modules/products/product.service.tsProduct → Typesense sync and DLQ.
src/shared/queues/search-sync-queueBullMQ dead‑letter queue for retries.

See Also


The Reshma-Core Team