How I measured an e-commerce load boundary
Test method
Isolated origin, CDN bypassed, declared page mix, constant arrival rate and latency, error and dropped-iteration thresholds fixed before testing.
The question was how much load an e-commerce origin could handle and which component would give way first. The test ran on an isolated VPS that was retired afterwards. The server now hosting the store was not stress tested.
A test of the origin
I ran k6 on a separate machine with a constant arrival rate. Each iteration requested one HTML page: home, category, product or search, in a mix set before the test. The CDN was bypassed, caches were warm, and the target used the correct HTTPS hostname and certificate. The test environment blocked email and outgoing calls. No orders or payments were submitted.
The criteria were set before increasing load: p95 below 3 seconds, fewer than 1% invalid responses and zero dropped iterations. Stages lasted 60 seconds and stopped at the first failure. Separate steady runs lasted 10 minutes. CPU and PHP-FPM state were sampled during the test; PHP profiling ran only on selected requests outside the k6 benchmark.
The observed boundary
In the final configuration, 3 HTML requests per second ran for 10 minutes: 1,802 requests including preflight, p95 1.102 seconds, no invalid responses and no dropped iterations. Mean sampled CPU was 66.41%.
The short stage at 5 requests per second passed, but CPU was about 96%, leaving little headroom. At 6 requests per second, completed responses were valid but latency crossed the limit. Profiling identified PHP work as the main observed constraint. Targeted changes were compared in paired steady runs, without adding their separate gains into a single guaranteed figure.
The short-stage pass/fail boundary moved from 4 passed and 5 failed in the initial test to 5 passed and 6 failed in the final configuration. Rates were tested only at integer steps and page selection was partly random, so this does not establish a precise percentage increase in capacity.
Limits
The final configuration was not held at 5 requests per second for 10 minutes. An earlier long run at that rate used a change to a vendor plugin that was later withdrawn; it cannot certify the final result. No stress test was run on the production server.
These figures count origin HTML requests, not simultaneous customers, complete browser page loads or orders. The test did not execute checkout transactions or include production background jobs. Establishing a safe operating threshold for the current server requires a new test in an isolated environment that represents it.
Anonymised at the client’s request.