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 whole customer journey, from the homepage landing to the payment confirmation. That path earns the revenue, and when any one step on it becomes a bottleneck, the failure cascades down the rest of it.
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. A sparse catalog returns 404s before the test reaches the endpoints that actually break.
Why full-funnel testing matters
Section titled “Why full-funnel testing matters”A checkout-only load test misses the most common BFCM failure: a slow product page that stops 98 % of users from reaching checkout at all. Put load on the full funnel, with realistic weights at each step, and you see where the system breaks under traffic shaped like your customers.
Real BFCM failures are rarely “payment is down.” More often they look like this:
- 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
A full-funnel test shows all of these.
The BFCM checkout journey
Section titled “The BFCM checkout journey”The journey has six stages. Each stage calls its own endpoints, and the VU weight at each stage follows the 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 Taurus, you write this as one scenario with all requests in sequence and think time between steps. The per-stage weights come from the think time and scenario branching. You can also use several scenarios with a weighted VU split.
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. Give each virtual user its own product ID. One shared ID produces cache-hit rates that production never sees.
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 never ran.
- Sort by p95 latency to find the slowest stage.
- Sort by error rate to find the stage with the most errors.
- 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 scenario over-weights checkout.
Under realistic funnel load, the payment endpoint is often faster than in isolation tests, because only 2 % of your VUs reach it. If payment p95 is slow in a full-funnel run, the problem is real and not a 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, which is not a realistic workload |
| Use randomized product IDs and search terms from a CSV | Use the same product/session in every VU and get artificial cache behavior |
| Set per-label failure criteria on critical endpoints | Use only a global error-rate criterion, which 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: push this full-funnel scenario past the modeled peak.
- Third-party and payment dependencies: 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.