At a glance
MySQL queries per second plotted on one axis against the storefront order rate on the other, in real time. The two should rise and fall together: more shoppers means more queries means more orders. When query volume spikes but the order rate stays flat, the extra load is not coming from real customers. It is almost always a bot, a scraper, or a misbehaving integration hammering the database for no commercial return. This card is the database-side detector for that pattern, and it protects both your infrastructure cost and your real shoppers’ performance.
| What it tracks | MySQL queries per second overlaid against the linked ecom connector’s live order rate, on a dual-axis chart, so you can see whether query load is matched by commercial activity. |
| Data source | MySQL side: Questions delta from SHOW GLOBAL STATUS, sampled to derive queries-per-second. Ecom side: live order rate (orders per minute / per interval) from the linked Shopify, BigCommerce, or Adobe Commerce connector. |
| Why it matters | A QPS spike that does not produce orders is load you are paying for with zero revenue, and it degrades performance for real shoppers. Detecting the decoupling early lets you rate-limit or block the source before it saturates connections or inflates your bill. |
| Reading the value | The two lines tracking together is healthy. QPS climbing while order rate stays flat is the alert pattern: query volume without commercial intent, the signature of a scraper or bot. |
| Time window | 15m (rolling, real-time sampled) |
| Alert trigger | qps spike with no order spike (= bot / scraper): a sustained rise in QPS not accompanied by a corresponding rise in order rate. |
| Roles | owner, engineering, operations |
Calculation
The MySQL side derives queries per second from theQuestions status counter, which increments on every statement the server executes (the related Queries counter additionally includes statements run inside stored procedures; Questions is the cleaner shopper-traffic proxy). The card samples the counter and divides the delta by the elapsed time:
Worked example
A storefront runs at a steady evening baseline of around 1,400 QPS and 6 orders per minute. On 14 Apr 26 at 21:10 BST a price-scraping bot discovers the catalogue search endpoint and starts crawling it hard. Snapshot of the 15-minute rolling window:| Time (BST) | QPS | Orders/min | Notes |
|---|---|---|---|
| 21:05 | 1,420 | 6 | Normal evening baseline |
| 21:10 | 2,650 | 6 | QPS up 87%, orders flat |
| 21:13 | 3,900 | 5 | QPS up 175%, orders slightly down |
| 21:16 | 4,200 | 5 | Real shoppers now feeling the slowdown |
/catalog/search), then rate-limit or block it at the CDN / WAF. Within minutes QPS falls back to baseline, the buffer-pool hit rate recovers, and the order rate returns to 6/min. The card confirms the fix by showing the QPS line drop back into alignment with the order line.
Three takeaways:
- Correlation is health; decoupling is the alarm. Two lines moving together means real shoppers. QPS without orders means load without commercial intent, and that is almost always something to stop.
- A scraper hurts twice. It costs infrastructure to serve, and it degrades real shoppers’ performance by evicting hot pages from the buffer pool. Pair with InnoDB Buffer Pool Hit Rate % to see the second effect.
- The fix lives upstream. The database cannot tell a bot from a human; the CDN, WAF, or application rate-limiter can. This card tells you to go there; it does not block traffic itself.
Sibling cards
| Card | Why pair it with QPS Spike vs Order Rate | What the combination tells you |
|---|---|---|
| Queries per Second (live) | The raw QPS reading without the order overlay. | This card adds the commercial context that tells a healthy spike from a bot spike. |
| MySQL Pool Saturation vs Traffic Burst | The connection-side cross-channel peer. | A bot spike can saturate the pool too; together they show the full load picture. |
| InnoDB Buffer Pool Hit Rate % | Scraper scans evict hot pages from cache. | Hit rate dropping during the QPS spike confirms the bot is hurting real shoppers’ performance. |
| Query Latency p95 (ms) | Added load slows everyone’s queries. | Rising p95 during the spike quantifies the slowdown real shoppers feel. |
| Slow-Query Rate % | Bot-driven scans often trip the slow-query log. | A slow-query spike co-occurring with the QPS spike points at expensive scraper queries. |
| Top 10 Slowest Queries (digest) | Identifies the exact query pattern the bot is running. | The scraper’s search query usually jumps to the top of this list during the event. |
| Aborted Connects (24h) | Some bots open and abandon connections. | A connect-abort spike alongside the QPS spike helps fingerprint the source. |
Reconciling against the source
Where to look in MySQL directly:On managed services, RDS and Aurora exposeSHOW GLOBAL STATUS LIKE 'Questions';sampled twice a few seconds apart, then divide the delta by elapsed seconds for QPS.SHOW GLOBAL STATUS LIKE 'Queries';for the broader count including stored-procedure statements.SELECT * FROM performance_schema.events_statements_summary_by_digest ORDER BY COUNT_STAR DESC LIMIT 10;to see which query pattern the volume is coming from.SHOW PROCESSLIST;during the spike to spot a single host or user driving the load.
Queries per second in CloudWatch and Performance Insights; Cloud SQL exposes queries per second in Cloud Monitoring and Query Insights. All compute QPS from the same Questions/Queries counters, so the database figure should reconcile cleanly; the order rate comes from the ecom connector, not from MySQL.
Why our number may legitimately differ from the native tooling:
| Reason | Direction | Why |
|---|---|---|
Questions vs Queries | Native value higher | Some dashboards chart Queries (includes statements inside stored procedures and prepared-statement internals); the card uses Questions as the cleaner shopper-traffic proxy. |
| Sampling interval | Peaks smoothed | The card derives QPS over its sampling cadence; an instantaneous native reading can show a sharper momentary peak. |
| Order-rate source | Not comparable | The order axis comes from the ecom connector and has no MySQL equivalent to reconcile against; reconcile it against the storefront’s own order report instead. |
| Time zone | Row timestamps shift | The card renders in the merchant’s display timezone; native tooling uses the server / account timezone. |
| Card | Expected relationship | What causes divergence |
|---|---|---|
shopify.total_revenue / linked ecom connector | The order-rate axis should match the connector’s live order feed. | A mismatch means the connector link is stale; reconcile the order axis against the storefront’s own report. |
mysql_qps | The QPS axis should equal the standalone live QPS card. | They read the same Questions counter; any difference is sampling timing. |
Known limitations / FAQs
QPS spiked but orders also spiked. Should I worry? No, that is exactly the healthy pattern: real shoppers arriving, querying, and converting. The card only alerts when QPS rises without a matching rise in orders. Correlated spikes are a flash sale or a campaign landing well; enjoy them, and check capacity cards like MySQL Pool Saturation vs Traffic Burst to be sure the database can carry the load. Could a legitimate event cause QPS without orders? Yes, a few. A new analytics or reporting integration that queries heavily but never places orders, a search-index rebuild, a cache warm-up job, or a price-comparison feed you actually authorised. The card cannot tell an authorised heavy reader from a hostile scraper; it tells you the decoupling is happening so a human can judge intent. Whitelist known heavy readers so they do not cry wolf. The order axis comes from the storefront, not the database. Why mix the two? Because the insight lives in the relationship between them, not in either number alone. The database knows how hard it is being worked; the storefront knows how much commerce that work produced. Putting them on one chart turns two ambiguous numbers into one clear question: is this load earning its keep? That is the whole point of a cross-channel card. How do I act on a confirmed bot spike? The database cannot block traffic, so act upstream. Identify the source fromSHOW PROCESSLIST and the access logs (usually one IP range, a non-browser user-agent, hitting a narrow set of endpoints), then rate-limit or block it at the CDN, WAF, or application layer. Watch the card afterwards: a successful block shows the QPS line dropping back into alignment with the order line.
A scraper that only reads should not affect my shoppers. Why does the order rate dip?
Because reads are not free. Heavy catalogue scans evict hot pages from the InnoDB buffer pool, so real shoppers’ queries start missing cache and running slower (visible on InnoDB Buffer Pool Hit Rate %). Slower pages mean some shoppers abandon, so the order rate dips even though the bot never bought anything. That second-order harm is exactly why catching the spike early matters.
Does this distinguish read QPS from write QPS?
The headline uses Questions, which counts all statement types. To separate them, drill into SHOW GLOBAL STATUS LIKE 'Com_select'; (reads) versus Com_insert/Com_update/Com_delete (writes). A scraper spike is almost entirely Com_select with no corresponding Com_insert for orders, which is another way to confirm the pattern.