End-to-end journey load
import Screenshot from ‘@components/Screenshot.astro’;
Most load tests cover a single endpoint. A BFCM readiness test must cover the entire customer journey from the moment a user lands on the homepage to the moment their payment is confirmed — because that is the path that generates revenue, and it is the path that fails in cascading ways when any single step becomes a bottleneck.
Before you start
Section titled “Before you start”- You have completed capacity planning and traffic modeling and have per-stage VU weights derived from your conversion funnel.
- A smoke test has passed for each individual endpoint in the journey.
- You have test user accounts (or anonymous session support) for the checkout flow.
- Your staging environment has a realistic product catalog — sparse catalogs return 404s before the real problem endpoints are even hit.
Why full-funnel testing matters
Section titled “Why full-funnel testing matters”A checkout-only load test misses the most common BFCM failure pattern: the bottleneck is not payment, it is a slow product page that prevents 98 % of users from ever reaching checkout. Running load against the full funnel, with realistic weights at each step, reveals where the system actually breaks under customer-shaped traffic.
Real BFCM failures are rarely “payment is down.” They are:
- Homepage CDN cache expires under traffic, hammering origin
- Search index returns timeouts because every arriving user searches immediately
- PDP personalization service (frequently skipped in load tests) becomes the bottleneck
- Session store hits its connection limit when cart-add requests spike
- Checkout service rate-limits payment processor calls, creating a queue that backs up into cart
Full-funnel testing surfaces all of these.
The BFCM checkout journey
Section titled “The BFCM checkout journey”The journey has six stages. Each stage calls specific endpoints, and the VU weight at each stage reflects conversion rates:
| Stage | Endpoints | Relative traffic |
|---|---|---|
| 1. Landing / category browse | GET /, GET /category/:id, GET /nav | 100 % |
| 2. Search | GET /search?q=..., GET /search/autocomplete | 40 % |
| 3. Product detail (PDP) | GET /product/:id, GET /product/:id/reviews, GET /product/:id/stock | 60 % |
| 4. Add to cart | POST /cart/items, GET /cart | 15 % |
| 5. Checkout | GET /checkout, PUT /checkout/address, PUT /checkout/shipping | 8 % |
| 6. Payment | POST /checkout/payment, GET /order/:id/confirmation | 2 % |
In a Taurus scenario, you implement this as a single scenario with all requests in sequence and think time between steps. The per-stage weights emerge naturally from the think time and scenario branching — or you can use multiple scenarios with weighted VU allocation.
Taurus scenario: weighted full funnel
Section titled “Taurus scenario: weighted full funnel”execution: - scenario: browse-to-confirm concurrency: 1360 ramp-up: 5m hold-for: 20m
scenarios: browse-to-confirm: think-time: 3s requests: # Stage 1: Landing page - url: https://api.staging.example.com/v1/homepage label: GET /homepage think-time: 4s
# Stage 2: Search (40 % of users search — model via data file randomization) - url: https://api.staging.example.com/v1/search?q=${SEARCH_TERM} label: GET /search think-time: 3s
# Stage 3: Product detail - url: https://api.staging.example.com/v1/products/${PRODUCT_ID} label: GET /product/:id - url: https://api.staging.example.com/v1/products/${PRODUCT_ID}/stock label: GET /product/:id/stock think-time: 5s
# Stage 4: Add to cart - url: https://api.staging.example.com/v1/cart/items label: POST /cart/items method: POST headers: Content-Type: application/json Authorization: Bearer ${SESSION_TOKEN} body: '{"product_id": "${PRODUCT_ID}", "qty": 1}' think-time: 2s
# Stage 5: Checkout - url: https://api.staging.example.com/v1/checkout/start label: POST /checkout/start method: POST headers: Authorization: Bearer ${SESSION_TOKEN} body: '{"cart_id": "${CART_ID}"}' think-time: 6s
# Stage 6: Payment (only ~25% of checkout starters complete payment) - url: https://api.staging.example.com/v1/checkout/payment label: POST /checkout/payment method: POST headers: Content-Type: application/json Authorization: Bearer ${SESSION_TOKEN} body: '{"payment_method": "card", "token": "${PAYMENT_TOKEN}"}'Use a CSV data entity (see Parameterise tests with CSV data) to supply realistic PRODUCT_ID, SESSION_TOKEN, CART_ID, and SEARCH_TERM values. Do not use the same product ID for every virtual user — you will create artificial cache-hit rates that are not present in production.
Per-endpoint failure criteria
Section titled “Per-endpoint failure criteria”Set failure criteria at the per-label level so each stage has its own SLO:
| Request label | p95 threshold | Error rate threshold |
|---|---|---|
GET /homepage | 300 ms | 0.1 % |
GET /search | 500 ms | 0.5 % |
GET /product/:id | 400 ms | 0.1 % |
GET /product/:id/stock | 200 ms | 1 % |
POST /cart/items | 600 ms | 0.5 % |
POST /checkout/start | 800 ms | 0.5 % |
POST /checkout/payment | 1200 ms | 0.2 % |
Payment gets the most generous latency budget (customers will wait longer to pay) but the tightest error rate budget (payment failures directly reduce revenue).
Reading the run result
Section titled “Reading the run result”Open the Overview tab and switch to the per-label breakdown:
- Check that each label appears in the results — a missing label means that part of the journey was not exercised.
- Sort by p95 latency to find the slowest stage.
- Sort by error rate to find the most error-prone stage.
- Look at throughput per label — the ratio
RPS(homepage) / RPS(payment)should be close to your conversion funnel ratio (100 : 2). If payment RPS is higher relative to homepage, your test scenario is over-weighting checkout.
The payment endpoint under realistic funnel load is often faster than it appears in isolation tests — because only 2 % of your VUs reach it. If payment p95 is slow in a full-funnel run, that is a real problem, not test artifact.
Do / don’t
Section titled “Do / don’t”| Do | Don’t |
|---|---|
| Weight scenario steps by real conversion funnel data | Send all VUs to the payment endpoint — it is not a realistic workload |
| Use randomized product IDs and search terms from a CSV | Use the same product/session in every VU — artificial cache behavior |
| Set per-label failure criteria on critical endpoints | Use only a global error-rate criterion — it hides per-stage failures |
| Verify every journey stage appears in the per-label breakdown | Trust that all steps ran just because the run finished |
| Run the funnel test before stress or spike tests | Spike-test an endpoint that was never part of a funnel test |
Where to go next
Section titled “Where to go next”- Spike and stress for sales — take this full-funnel scenario and push it past the modeled peak.
- Third-party and payment dependencies — understand how to model payment gateway calls realistically.
- Failure criteria pass/fail gates — set the per-label thresholds that gate your go/no-go decision.
- Parameterise tests with CSV data — supply realistic product IDs, session tokens, and search terms.