Skip to main content

Flow: Search Query

The most frequent customer operation. A search request enters via the Cloudflare search proxy worker and is routed to Marqo.

Request Path

Step-by-Step

1. Worker Entry

Where: components/search_proxy/src/worker.tsapp.ts

The Hono app receives POST /api/v1/indexes/:index/search.

Logs:

{"message": "request_start", "method": "POST", "path": "/api/v1/indexes/{index}/search"}

Inspect: Tail the worker — see Cloudflare Workers.

npx wrangler tail {env}-ecom-api

2. Authentication

Where: components/search_proxy/src/middleware.tsdirect/platform.ts

Two auth methods (checked in order):

  1. Index ID header: x-marqo-index-id: {system_account_id}-{index_name} (read-only operations)
  2. API key: Authorization: Bearer {api_key}

Failure: 401 with "Missing API key or index ID header".

Logs (DEBUG level; only logged at info if total >250ms):

{"message": "direct_auth_settings_readonly_timing", "auth_ms": 1.5, "settings_ms": 8.2}

3. Settings Retrieval from KV

Where: components/search_proxy/src/direct/platform.ts

  1. Resolve shop ID from API key (calls admin server) or extract from x-marqo-index-id header
  2. env.KV.get(shopId) → JSON settings with index endpoint, API key, search config, feature flags

Failure: 404 "Not configured" if shop ID not in KV.

Inspect: Check KV contents — see Cloudflare Workers.

Logs:

{"message": "index_settings_timing", "shop_id": "...", "has_value": true, "timings": {"index_settings_kv_get_ms": 6.0}}

If settings missing: Check whether the Settings Sync flow completed successfully.

4. Read Alias Resolution (Optional)

Where: components/search_proxy/src/middleware.ts

If read_alias (legacy) or index_aliases.doc_reads (new) is configured and enabled is true, traffic is routed to alias targets using deterministic hash bucketing (FNV-1a on userId/sessionId). A single target at weight 1.0 skips bucketing.

Setting enabled: false preserves config but stops routing — this is the primary rollback mechanism. See Aliasing.

Logs:

{"message": "read_alias_redirect", "original_index": "...", "aliased_index": "..."}

5. Query Config Override Lookup (Optional)

Where: components/search_proxy/src/query_overrides.ts

If feature_flags.qcfg_overrides is enabled:

  1. Normalize query → compute shard hash
  2. Check shard cache (10 min TTL) → KV_QCFG namespace
  3. Apply overrides: query replacement, config deep-merge, lexical expansion, quote mode

Timeout protection: 70ms max. If exceeded, proceeds with base settings.

Logs:

{"message": "qcfg_shard_cache_lookup", "cache_hit": true}
{"message": "qcfg took 3.21ms"}

6. Search Request Building

Where: components/search_proxy/src/search.ts

Transforms the customer request into a Marqo API request:

  • Merges search config defaults (limit, offset, facets, sort, filter)
  • Applies query prefix, collapse fields, score modifiers
  • Handles image queries and multi-term queries (switch to tensor-only hybrid)
  • Applies lexical expansion and quoting

7. Redirect Check (Parallel)

Where: components/search_proxy/src/redirects/redirects.ts

Runs in parallel with the Marqo search:

  1. Check Cloudflare Cache API (configurable TTL, default 10 min)
  2. On miss: query SearchRedirectTable in DynamoDB (pk={accountId}#INDEX#{indexName}, sk=QUERY#{normalizedQuery})
  3. Background cache update via ctx.waitUntil()

Inspect: Check redirects in DynamoDB — see DynamoDB.

If a redirect is found, it takes priority over search results.

8. Marqo Search Execution (Parallel)

Where: components/search_proxy/src/search.ts

POST {settings.marqo_index_url}/indexes/{index_name}/search
Headers: x-api-key: {marqo_api_key}

Sent via MARQO_WORKER service binding (not direct HTTP).

Logs:

{"message": "marqo_search_response", "hitsCount": 12, "processingTimeMs": 45, "cacheHit": true, "totalHits": 150}

9. Response Assembly

If redirect found → return { redirect: { url, query } }. Otherwise → return { hits, totalHits, query, limit, offset, facets, processingTimeMs }.

Documents are transformed: internal fields (_merch_*, _pixel_*) removed, flattened maps unflattened.

10. Metrics Enqueue (Background)

Where: components/search_proxy/src/metrics.ts

Non-blocking ctx.waitUntil() sends a metric event to SQS:

  • Endpoint, status, latency, cache hit, geolocation (from Cloudflare headers)
  • Queue: {env}-EcomMetricsQueue

Logs:

{"message": "request_end", "status": 200, "reqStartMs": ..., "reqEndMs": ...}

Inspect: Check queue depth — see SQS.

What to Look For

SymptomWhere to Check
401 errorsAuth headers missing or malformed. Tail worker logs.
404 "Not configured"Settings not in KV. Check Settings Sync flow.
Slow searches (>500ms)Check settings_ms in timing log (DEBUG level unless >250ms). KV cache miss? Check processingTimeMs for Marqo latency.
Wrong resultsCheck query overrides (qcfg_* logs). Check read alias bucketing. Check filter applied.
Stale resultsKV cache TTL. Check settings exporter ran — see Settings Sync.
Empty resultsCheck filter expression in marqo_search_request log. Check index has documents.
Redirect not workingCheck SearchRedirectTable in DynamoDB. Check redirect cache.
Metrics missingCheck SQS queue health. Check EcomMetricsWorker Lambda — see Lambda.