Where does the shop break when visitors come to buy, not to look?
Online shop on Black Friday
Holds ~30 req/s on short steps (2.1 min), fails at ~35 req/s
Failed checks: Choose shipping errors 1.2 % > 1 %, Open categories errors 1.4 % > 1 %, Search errors 1.8 % > 1 %.
- Holds
- ~30req/s
- measured over 2.1 min
- Fails at
- ~35req/s
- judged by the SLO
Checked 6 of 12 steps at this rate; 6 not checked — too few samples (< 100 in the window)
- Choose shipping
- Place the order
- Start payment
- Open the payment session
- See shipping options
- Enter the address
rate steps of 2.1–7 min · checks: 149 passed, 5 failed, 6 too little data, 0 not run · sent 99 % of the plan · generator health not verified
Synthetic load sent from outside; your real traffic and server metrics are not part of it.
What to do next
- Confirm it with a load test at ~24 req/s.
- To check Choose shipping, Place the order, Start payment and 3 more, run at least 4.7 min at this rate: they had fewer than 100 samples.
The large catalog under a sale-day visit mix at a steady rate: fewer browsers, more carts and orders per visit. It models the mix, not a sale-day traffic spike.
Example: a real CapacityLab Load Run against a shop we host
Test setup
Where the limit lies
Each dot is a rate the shop was held at for at least a minute and a half. It passes when every step of the visit with enough samples keeps its p95 latency inside the bound and errors under 1%; a rare checkout step with too few samples at that rate is shown as missing, not as passed.
- Held for 30 min24.5 req/s
- Held for 60 min24.5 req/s
- Held for 180 min24.5 req/s
- Held for 720 min24.5 req/s
- Slowed first
- Search
- Latency bound
- p95 ≤ 1.5 s
Planned against delivered
The search climbs a staircase of rates. At each step our generators sent the planned rate; the bars show what the shop actually answered, and its p95 latency at that step.
| Planned | Delivered | p95 | Errors | Result |
|---|---|---|---|---|
| 30.3 | 29.9 | 750 ms | 0.5% | Held |
| 35.3 | 35 | 750 ms | 0.65% | Broke |
| 41.2 | 40 | 750 ms | 0.75% | Broke |
| 48 | 47.2 | 750 ms | 0.93% | Broke |
- Choose shipping: 1.18% of requests failed, against 1% allowed.
- Open categories: 1.39% of requests failed, against 1% allowed.
- Search: 1.84% of requests failed, against 1% allowed.
- Search: 2.87% of requests failed, against 1% allowed.
Which step slowed down first
p95 latency of each step of the visit at each rate, against the bound. The step the Result names as limiting is marked.
| Step of the visit | Share | 30.3 req/s | 35.3 req/s | 41.2 req/s |
|---|---|---|---|---|
Load the regionGET /store/regions | 3.9% | 75 ms0.7% errors | 100 ms | 100 ms0.6% errors |
Open categoriesGET /store/product-categories | 8.6% | 100 ms0.6% errors | 75 ms1.4% errors | 100 ms0.5% errors |
Browse the catalogGET /store/products | 24% | 100 ms0.7% errors | 100 ms0.3% errors | 100 ms0.4% errors |
SearchLimitingGET /store/products | 12% | 750 ms0.9% errors | 750 ms1.8% errors | 750 ms2.9% errors |
Open a productGET /store/products/{product_id} | 37% | 100 ms0.3% errors | 100 ms0.5% errors | 100 ms0.6% errors |
Add to cartPOST /store/carts | 3.9% | 500 ms0.7% errors | 500 ms | 500 ms |
Enter the addressPOST /store/carts/{cart_id} | 2.2% | — | 1,000 ms0.6% errors | 750 ms0.7% errors |
See shipping optionsGET /store/shipping-options | 2.2% | — | 300 ms | 300 ms |
Choose shippingPOST /store/carts/{cart_id}/shipping-methods | 2.2% | — | 1,500 ms1.2% errors | 1,000 ms0.4% errors |
Start paymentPOST /store/payment-collections | 1.2% | — | 300 ms | 300 ms0.7% errors |
Open the payment sessionPOST /store/payment-collections/{payment_collection_id}/payment-sessions | 1.2% | — | 200 ms | 200 ms |
Place the orderPOST /store/carts/{cart_id}/complete | 1.2% | — | 1,000 ms | 1,000 ms |
p95, SLO ≤ 1,500 ms
Holding it for longer
A capacity search finds the limit in minutes. Longer runs at a rate below it show whether the shop keeps holding: slow leaks, full queues and cold caches take time to show.
- Find the limitLimit found — provisionalHolds ~30 req/s on short steps (2.1 min), fails at ~35 req/sOct 2, 2026, 16:05 UTC
- Hold 30 minHeld24.6 req/s delivered, p95 500 ms, errors 0%Sep 30, 2026, 18:45 UTC
- Hold 1 hHeld24.4 req/s delivered, p95 500 ms, errors 0.01%Sep 30, 2026, 19:17 UTC
- Hold 3 hHeld24.5 req/s delivered, p95 500 ms, errors 0%Sep 30, 2026, 20:19 UTC
- Hold 12 hHeld24.5 req/s delivered, p95 500 ms, errors 0.04%Sep 30, 2026, 23:34 UTC
What we saw on our own servers
This is the one part a Report does not contain: we host this shop, so we can read its hosting metrics. On your application you read your own dashboards; CapacityLab measures from the outside.
- Application (Node.js)1.28 vCPUMemory peak 678 MB
- Database (PostgreSQL)11 vCPUMemory peak 5,328 MB
- Cache (Redis)0.02 vCPUMemory peak 28 MB
The database was the busier side: its CPU peaked at 11 vCPU while the application stayed at 1.28. Its CPU was not capped, so this shows where the work went, not that the database ran out; search over a catalog this large is database work and a likely place for visitors to queue, but locks and query plans were not measured.
188 of 47,592 requests ended with a server error.
What you would do next
- Confirm before you plan
Run a load test at 24.2 req/s for 30 minutes: the search advises it as the rate to confirm next, and only the confirmation shows whether every step keeps its bound.
- Watch your side while it runs
Keep your own dashboards open during the run. The report says which step slowed; your metrics say why.
- Change one thing, then compare
After a change, run the same test again and put the two reports side by side.
Your own copy of this report is one sign-up away
Sign up with your email. Your new account opens with this report and every other demo report inside, ready to compare with your own first run.
Where these numbers come from
Exported from the published Reports of these Load Runs. The shop's CPU and memory come from its Railway metrics; its error count from its own access log.
Identifiers and checksums
| Load Run | Result digest | Computed |
|---|---|---|
2f2bc0b7-b0c8-49a3-82d4-1c138209e73b | sha256:386667c70d9ca0840cdee6aeb1acd1a6c07e3922ec9adb555910568ba8dfd39e | Oct 2, 2026, 16:25 UTC |
4d174fec-5654-4ade-a097-f56b69567486 | sha256:b67c3b95dc3c4ae89398b1c4910ae7c7fb08ee5904f5e7ba37df34630432e2c4 | Sep 30, 2026, 19:16 UTC |
0eacc785-d9b2-4233-971f-e7e55af25f05 | sha256:860d8d217e03cc4923877b350f95fbd864151bbb07a460e7b05b0d040db2385b | Sep 30, 2026, 20:18 UTC |
843bd07c-9dc7-4e21-b0e2-5e3e983ade22 | sha256:3bc313613e1fa767f8632d5143cacee30d4958ffde2585f3dc41db8f5700425b | Sep 30, 2026, 23:20 UTC |
172d3b8d-a7de-423e-987a-ffd27b0dd14b | sha256:f85696037294e3e70e8e607c4ee8298c4b8b648ae8881a53da7bf4501642e83f | Oct 1, 2026, 11:37 UTC |