Commit 891da0fb3d9 for woocommerce

commit 891da0fb3d9d3237ea4276cd1a888497f79240b4
Author: Vladimir Reznichenko <kalessil@gmail.com>
Date:   Mon Apr 27 09:17:14 2026 +0200

    [Performance] BFCM stress-test config finalization (#64412)

diff --git a/plugins/woocommerce/tests/performance/tests/bfcm.js b/plugins/woocommerce/tests/performance/tests/bfcm-infra-hammered.js
similarity index 60%
rename from plugins/woocommerce/tests/performance/tests/bfcm.js
rename to plugins/woocommerce/tests/performance/tests/bfcm-infra-hammered.js
index 3f3729d3b8c..800aaf22e6e 100644
--- a/plugins/woocommerce/tests/performance/tests/bfcm.js
+++ b/plugins/woocommerce/tests/performance/tests/bfcm-infra-hammered.js
@@ -9,24 +9,29 @@ import { checkoutCustomerLogin } from '../requests/shopper/checkout-customer-log
 // This test runs at the environment's saturation ceiling — thresholds will fail by design.
 // Use the following metrics to detect regressions (numbers go up) or improvements (numbers go down):
 //
-//   STABLE SIGNALS — not dominated by Apache spike timing; reliable across single runs:
-//   - http_req_duration p(50)   — baseline 101ms; fast-path latency; reflects requests completing before Apache queues up;
-//                                 regressions surface here first; not materially affected by spike minutes.
-//   - Store API checkout med    — baseline 1.03s; most sensitive to checkout-path optimizations (DB writes, order creation);
-//                                 p(90)/p(95) are capped at 60s during spike minutes — use median, not tail percentiles.
-//   - update-customer med       — baseline 66ms; p(90) baseline 2.65s; checkout address persistence path.
-//   - Order Received p(90)      — baseline 1.19s; downstream of checkout; sensitive to order creation overhead.
-//   - order completion rate     — baseline 73% ('body contains: order_id' check; 176/239 attempts); proportion of flows
-//                                 that reach order received; more stable than http_req_failed when Apache varies run-to-run.
+//   STABLE SIGNALS — low run-to-run variance (validated across 3-run sets); reliable within a single run:
+//   - http_req_duration p(50)   — baseline ~102ms (±13ms across 3 runs); fast-path latency; reflects requests
+//                                 completing before Apache queues up; regressions surface here first.
+//   - update-customer med       — baseline ~68ms (±4ms across 3 runs); tightest signal available; checkout
+//                                 address persistence path; not materially affected by spike minutes.
 //
-//   NOISY SIGNALS — dominated by which minute the Apache spike hits; compare trends across multiple runs, not single pairs:
-//   - http_req_failed rate      — baseline 4.05%; spikes when Apache worker pool exhausts; volatile run-to-run.
-//   - dropped_iterations        — baseline 278; K6 drops iterations when VU pool exhausts due to slow Apache; volatile.
-//   - iteration_duration avg    — baseline 52.26s; pulled up by spike minutes; use as trend indicator, not per-run comparison.
-//   - Store API checkout avg    — baseline 16.26s; dragged by 60s timeout outliers during spike minutes; median is more reliable.
+//   MODERATELY STABLE — lower variance than noisy signals; compare 3+ runs for directional confidence:
+//   - order completion rate     — baseline ~73% ('body contains: order_id' check); proportion of flows that
+//                                 reach order received; 8% run-to-run variance in baseline set; more stable
+//                                 than http_req_failed but still sensitive to overall load conditions.
 //
-// A PR that reduces DB queries or checkout overhead will move stable signals in the right direction even
-// if the test still "fails" thresholds — less failing is a measurable win. Baseline is as of April 2026.
+//   NOISY SIGNALS — dominated by which minute the Apache spike hits; never compare single runs:
+//   - Store API checkout med    — 3x swings within baseline set alone (346ms–1.21s); spike timing determines
+//                                 whether requests queue before/after median; use avg as trend only.
+//   - Order Received p(90)      — 10x swings (160ms–2.58s); spike-minute timing dominant.
+//   - update-customer p(90)     — 2–3x swings (2.94s–6.73s); tail dominated by queuing during spike minutes.
+//   - http_req_failed rate      — baseline 4–9% across runs; spikes when Apache worker pool exhausts; volatile.
+//   - dropped_iterations        — baseline ~310; K6 drops iterations when VU pool exhausts; volatile.
+//   - iteration_duration avg    — pulled up by spike minutes; use as trend indicator, not per-run comparison.
+//   - Store API checkout avg    — dragged by 60s timeout outliers during spike minutes; median no better.
+//
+// A PR that reduces DB queries or checkout overhead will move stable signals in the right direction even  if the test
+// still "fails" thresholds — less failing is a measurable win. Baselines validated April 2026 across 3-run sets.

 export const options = {
 	// Saturation profile (M4 Pro, wp-env defaults):
diff --git a/plugins/woocommerce/tests/performance/tests/bfcm-infra-holdingup.js b/plugins/woocommerce/tests/performance/tests/bfcm-infra-holdingup.js
new file mode 100644
index 00000000000..b50ae839db8
--- /dev/null
+++ b/plugins/woocommerce/tests/performance/tests/bfcm-infra-holdingup.js
@@ -0,0 +1,113 @@
+/**
+ * Internal dependencies
+ */
+import { cart } from '../requests/shopper/cart.js';
+import { checkoutGuest } from '../requests/shopper/checkout-guest.js';
+import { checkoutCustomerLogin } from '../requests/shopper/checkout-customer-login.js';
+
+// Sub-saturation checkout DB performance test.
+//
+// Purpose: measure PHP/DB latency on the checkout path (order saves, customer saves, etc.)
+// without Apache worker exhaustion masking the signal. At 0.3 checkout/s Apache workers
+// stay well below the spike zone (~10–20/150), so median and p(90) reflect actual
+// server-side processing time rather than queue wait time.
+//
+// Contrast with bfcm-infra-hammered.js, which runs at the saturation ceiling (0.8/s) where Apache
+// dominates and only p(50) / update-customer median are reliable signals.
+//
+// All signals below are stable at this load level (validated across 3-run sets, April 2026):
+//
+//   - p(50) overall             — baseline ~77ms (±1ms); reflects fast-path latency; minimal variation.
+//   - Store API checkout med    — baseline ~472ms (±67ms); most sensitive to order-path optimizations
+//                                 (DB writes, order creation); stable here unlike at saturation.
+//   - Store API checkout p(90)  — baseline ~2.99s (±1.73s); noisier than median due to occasional
+//                                 outliers (WP-cron, cache misses); directionally reliable across 3+ runs.
+//   - update-customer med       — baseline ~65ms (±1ms); tightest signal; checkout address persistence path.
+//   - update-customer p(90)     — baseline ~77ms (±5ms); reliable here (no Apache queuing to inflate tail).
+//   - Order Received p(90)      — baseline ~121ms (±7ms); downstream of checkout; stable.
+//   - order completion rate     — baseline 100%; any drop below 100% indicates a correctness regression.
+//   - http_req_failed           — baseline 0%; meaningful signal here (not spike noise as in hammered.js).
+//   - dropped_iterations        — baseline ~3; near-zero confirms sub-saturation; spike = VU config issue.
+//
+// Note: Store API checkout p(95) fails the 1000ms threshold in both baseline and less-writes sets
+// (range 2.5–4.8s) due to infrequent outlier requests. This threshold is aspirational; watch the
+// median and p(90) for directional signals, not p(95).
+//
+// Requires a clean Apache baseline — restart the WordPress container between runs:
+//   bash plugins/woocommerce/tests/performance/utils/init-environment.sh
+//
+// Comparing runs: a single run is sufficient for directional confidence at this load level.
+// Run 2–3 times if you want variance bounds on noisy signals (checkout p(90)).
+
+export const options = {
+	// Sub-saturation profile (M4 Pro, wp-env defaults):
+	// - Total: 2/10s guest + 1/10s customer = 0.3 checkout/s.
+	// - Apache workers stay at ~10–20/150; no spike zone, no request queuing.
+	// - At this rate all iterations complete; dropped_iterations should be near zero.
+	// - See bfcm-infra-hammered.js for the saturation ceiling profile and its measurement limitations.
+	scenarios: {
+		// Guest checkout: 60% of checkouts.
+		checkout_guest: {
+			executor: 'ramping-arrival-rate',
+			exec: 'checkoutGuestFlow',
+			startRate: 1,
+			timeUnit: '10s',
+			preAllocatedVUs: 3,
+			maxVUs: 6,
+			stages: [
+				{ duration: '4m', target: 2 }, // Ramp to peak.
+				{ duration: '8m', target: 2 }, // Sustain peak.
+				{ duration: '2m', target: 0 }, // Ramp down.
+			],
+		},
+		// Authenticated checkout: 40% of checkouts.
+		checkout_customer: {
+			executor: 'ramping-arrival-rate',
+			exec: 'checkoutCustomerLoginFlow',
+			startRate: 1,
+			timeUnit: '10s',
+			preAllocatedVUs: 2,
+			maxVUs: 4,
+			stages: [
+				{ duration: '4m', target: 1 }, // Ramp to peak.
+				{ duration: '8m', target: 1 }, // Sustain peak.
+				{ duration: '2m', target: 0 }, // Ramp down.
+			],
+		},
+	},
+	thresholds: {
+		// Aggregate thresholds across all requests.
+		http_req_duration: [ 'p(50)<200', 'p(90)<500', 'p(95)<1000' ],
+		http_req_failed: [ 'rate<0.01' ],
+
+		// Per-request thresholds: cart workflow.
+		'http_req_duration{name:Shopper - wc-ajax=add_to_cart}': [
+			'p(95)<500',
+		],
+		'http_req_duration{name:Shopper - wc-ajax=get_refreshed_fragments}': [
+			'p(95)<200',
+		],
+		'http_req_duration{name:Shopper - View Cart}': [ 'p(95)<500' ],
+
+		// Per-request thresholds: checkout workflow.
+		'http_req_duration{name:Shopper - View Checkout}': [ 'p(95)<500' ],
+		'http_req_duration{name:Shopper - Login to Checkout}': [ 'p(95)<500' ],
+		'http_req_duration{name:Shopper - Store API update-customer}': [
+			'p(95)<200',
+		],
+		'http_req_duration{name:Shopper - Store API checkout}': [
+			'p(95)<1000',
+		],
+		'http_req_duration{name:Shopper - Order Received}': [ 'p(95)<500' ],
+	},
+};
+
+export function checkoutGuestFlow() {
+	cart();
+	checkoutGuest();
+}
+
+export function checkoutCustomerLoginFlow() {
+	cart();
+	checkoutCustomerLogin();
+}