Skip to main content
Card class: HeroCategory: Cross-Channel: Revenue at Risk

At a glance

This dual-axis card plots Elasticsearch search queries per second against storefront traffic (sessions or page views from the connected ecom/analytics source) over the same window. In a healthy store the two lines move together: more shoppers means more searches. The signal you are watching for is divergence. A spike in search QPS with no matching spike in real traffic almost always means something non-human is hitting search: a runaway crawler, a scraper, a misbehaving integration, or an autocomplete loop firing a query on every keystroke. Catching this matters because bot-driven QPS consumes the same search thread pool and JVM heap that paying customers need, so it can degrade or take down search for everyone while generating zero revenue.
What it tracksTwo series on one chart: (axis 1) Elasticsearch search QPS, derived from the indices.search.query_total delta over time; (axis 2) ecom storefront traffic (sessions/page views) from the connected commerce or analytics connector, over the same 15-minute window.
Data sourceElasticsearch side: node/index search stats (indices.search.query_total) sampled and differenced to a per-second rate. Ecom side: the connected storefront’s traffic series (Shopify/BigCommerce/Adobe sessions, or GA4 if connected). The card aligns both to the same time buckets.
Time window15m. The card shows the most recent 15 minutes at a fine resolution so a sudden divergence is visible within a refresh or two.
Alert triggerA QPS spike with no corresponding traffic spike. The pattern (search volume jumps while sessions stay flat) is flagged because it indicates a bot/crawler rather than real demand.
Cross-channel joinThis card is meaningless without an ecom or analytics connector: the comparison series is the storefront traffic, not anything Elasticsearch knows about.
Why divergence mattersBot QPS competes for the search thread pool, file-system cache, and heap. A scraper can saturate search and push real shoppers into slow queries or timeouts while contributing nothing to revenue.
What does NOT countIndexing operations (these are tracked separately by the indexing-rate card); internal monitoring or health-check queries if they are excluded by the connector’s filter.
Rolesowner, engineering, operations, security

Calculation

The Elasticsearch series is a rate computed from a monotonically increasing counter:
qps(t) = ( query_total(t) - query_total(t-1) ) / (seconds between samples)
   where query_total = sum over shards of indices.search.query_total
indices.search.query_total counts query-phase executions, so a single user search that fans out across N shards increments the counter N times. The card normalises for this where shard count is known, but the headline trend is what matters: the shape of the curve, not an exact per-user figure. The ecom traffic series is taken at face value from the connector (sessions or page views per bucket) and plotted on the second axis with its own scale, which is what “dual axis” means: the two lines can have very different magnitudes and still be compared by shape. The divergence detector looks at correlation over the 15-minute window. In normal operation search QPS and traffic are tightly correlated (shoppers search as they browse). The alert fires when QPS rises sharply while the traffic line stays flat, breaking that correlation. A flat-traffic, rising-QPS pattern is the classic non-human signature, so the card calls it out as a likely bot/crawler.

Worked example

A fashion retailer on BigCommerce uses a managed Elasticsearch cluster for product search and autocomplete. Storefront traffic is connected via the BigCommerce connector. Snapshot covers the 15 minutes from 13:20 to 13:35 GMT on 22 May 26.
Time bucketSearch QPSStorefront sessions/minReading
13:20 to 13:2490 to 110480 to 510Lines move together, healthy
13:25 to 13:29340 and rising495QPS tripled, sessions flat
13:30 to 13:34610 sustained500Clear divergence, alert fires
The dual-axis chart shows the blue QPS line climbing steeply away from the flat orange sessions line. The Vortex IQ headline flags QPS spike with no traffic spike (likely bot/crawler). The platform team works the problem:
  1. Confirm it is not real demand. Sessions are flat at ~500/min, exactly where they have been all afternoon. There is no email send, no paid-media burst, no flash sale in the calendar. Real shoppers did not suddenly start searching 6x harder.
  2. Identify the source. A quick look at the cluster’s hot threads and the load balancer access logs shows a single user-agent issuing paginated match_all queries against the products index, deep-paging through results, a textbook scraper. It is not coming through the storefront search box (those would create sessions), which is exactly why the traffic line never moved.
  3. Assess the collateral damage. During the spike, Search Latency p95 climbed from 120ms to 480ms and HTTP Connection Saturation touched 88%. Real shoppers were being slowed by the scraper. That is the revenue-at-risk: not the bot’s queries (worthless), but the degradation it inflicts on genuine sessions.
Impact framing (illustrative):
  - Real sessions during the spike: ~500/min, unchanged
  - Real search latency p95: 120ms -> 480ms (4x) while bot ran
  - Conversion sensitivity: every +100ms search latency shaves measurable
    conversion on search-led journeys
  - The bot generated 0 revenue while degrading every real shopper's search
  1. Mitigate. The team rate-limits the offending source at the edge (WAF/CDN), and QPS drops back to ~100 within a minute while sessions stay flat. The two lines reconverge. They then add a standing rule to block deep match_all pagination from unauthenticated clients.
Three takeaways for the platform team:
  1. Search QPS in isolation is ambiguous; against traffic it becomes diagnostic. A QPS jump could be a genuine demand surge or a bot. The only way to tell at a glance is the second line. If traffic rose too, celebrate; if it did not, investigate.
  2. Bots cost you through contention, not through their own queries. The danger is the heap, thread pool, and connection capacity the bot steals from paying customers, which is why this card sits in Revenue at Risk despite measuring a non-revenue actor.
  3. The inverse pattern is also worth a glance. Traffic rising while QPS stays flat can mean search is broken or the search box is not loading, shoppers are landing but cannot search. Same chart, opposite divergence, also actionable.

Sibling cards

CardWhy pair it with this cardWhat the combination tells you
Search Queries per Second (live)The raw QPS series this card overlays on traffic.Use it for the absolute number; use this card to judge whether the number is justified.
Search Latency p95 (ms)The shopper-facing cost of a QPS spike.Divergent QPS plus rising p95 confirms the bot is degrading real search.
HTTP Connection Saturation %The capacity ceiling a spike pushes against.Saturation climbing with bot QPS means real shoppers are about to be refused connections.
JVM Heap Used %Heavy or deep queries from a scraper inflate heap.Heap climbing alongside divergent QPS warns of GC pressure and possible circuit breakers.
Slow-Query Rate %Scrapers often issue expensive deep-pagination queries.A jump in slow-query rate during the spike pinpoints expensive bot queries.
Search Error Rate %The failure mode if the spike overwhelms search.Errors rising during divergent QPS means real shoppers are now getting failed searches.
ES Search Pool Saturation vs Ecom BurstThe capacity-focused cross-channel peer.Read together to separate “too many queries” from “queries from the wrong source”.
ES Product Index Doc Count vs Ecom CatalogThe correctness cross-channel peer.One watches volume vs demand; the other watches catalogue completeness.

Reconciling against the source

Where to look in Elasticsearch and the storefront:
GET /_nodes/stats/indices/search and GET /<index>/_stats/search expose query_total and query_time_in_millis; differencing query_total over time reproduces the QPS series. GET /_nodes/hot_threads during a suspected spike shows which queries are eating CPU, useful for identifying a scraper’s query shape. Your load balancer / CDN / WAF access logs are the authoritative source for “who is sending these queries”; Elasticsearch counts the queries but the edge identifies the client. On the storefront side, reconcile the traffic line against the platform’s own analytics (BigCommerce/Shopify/Adobe reporting, or GA4 real-time) for the same 15 minutes.
Why our number may legitimately differ from a raw stats read:
ReasonDirectionWhy
Shard fan-outraw query_total higher than per-user QPSOne user query increments the counter once per shard searched; the card normalises where shard count is known.
Sampling intervalsmoothingQPS is a delta between samples; a coarser sample interval averages out sub-bucket bursts.
Internal/health queriesraw slightly higherMonitoring pings hit search too; the card can exclude known internal sources if the connector is configured to.
Traffic-source definitionsecond-axis shape”Sessions” vs “page views” vs “users” scale differently; only the shape matters for divergence, but confirm which metric the connector supplies.
Time zoneaxis labels onlyElasticsearch stats are UTC; the card renders the 15m axis in your Vortex IQ display time zone.
Cross-connector reconciliation:
CardExpected relationshipWhat causes divergence
google_analytics.realtime_usersThe traffic line should track GA4 real-time users closely if GA4 is the source.If GA4 shows a surge the storefront connector does not, the connectors are measuring different scopes.
Storefront sessions (Shopify/BigCommerce/Adobe)The second axis equals the platform’s own session count for the window.A mismatch usually means bot traffic is being filtered out of analytics but still hitting search, which is exactly the signal this card surfaces.

Known limitations / FAQs

Search QPS spiked but so did traffic. Is that an alert? No. When both lines rise together it is genuine demand: an email send, a flash sale, a paid-media burst, or organic interest. The card only flags the case where QPS diverges from traffic. A correlated spike is a capacity question (watch HTTP Connection Saturation and JVM Heap Used %), not a “wrong source” question. Why is query_total higher than the number of searches I think happened? Because Elasticsearch counts the query phase per shard. A search that touches 5 shards adds 5 to query_total. The card normalises for this where it can, but for trend purposes the shape of the curve is what matters, not an exact per-user count. If you need exact user-level search counts, instrument the application layer instead. An autocomplete box fires a query on every keystroke. Does that look like a bot? It can. Aggressive autocomplete (one Elasticsearch query per keystroke, no debounce) multiplies QPS far faster than sessions grow, producing exactly the divergence this card flags. The fix is on the front end: debounce keystrokes, cache prefixes, and use the search-as-you-type or completion suggester so the query is cheap. The card is doing its job by surfacing the pattern. The traffic line is flat at zero but QPS is normal. What does that mean? Either the storefront/analytics connector is not reporting (broken connector, expired token) or you genuinely have no live sessions while a scheduled job still queries search. Check the connector health first; a missing traffic line makes the comparison meaningless and can produce a false bot signal. Can I see which client is causing the spike from this card? Not directly. Elasticsearch counts the queries but does not, by default, attribute them to a client IP or user-agent. To identify the source, correlate the spike window with your load balancer, CDN, or WAF access logs, and use GET /_nodes/hot_threads to see the query shape. Once identified, rate-limit or block at the edge. Is blocking the bot the right response, or should I scale the cluster? Scale only for real demand. Adding nodes to absorb scraper traffic is paying to serve queries that generate no revenue. The correct response to a divergent (bot) spike is to rate-limit or block the source at the edge. Reserve scaling decisions for correlated spikes where real shoppers are driving the load. Does this card include indexing load? No. This card is about the search path only (indices.search.query_total). Indexing throughput is tracked separately by Indexing Rate (docs/sec). Keeping them separate matters because a search spike and an indexing spike have completely different causes and remedies.

Tracked live in Vortex IQ Nerve Centre

Search QPS Spike vs Ecom Traffic is one of hundreds of KPI pulses Vortex IQ tracks across Elasticsearch and 70+ other ecommerce connectors. Nerve Centre runs the detection layer; Vortex Mind investigates the cause when something moves; Ask Viq lets you interrogate any number in plain English. Start for free or book a demo to see this metric running on your own data.