Load testing a Stripe integration without hitting Stripe
Run a k6 load test at 10k VUs against a Stripe mock. No rate limits, no cost, no flaky sandbox — just your code under real load.
The Problem
You've built a checkout flow. Your team wants to load test it before the product launch. The flow calls Stripe — to create a payment intent, confirm it, maybe retrieve a customer record. You set up k6, ramp to 500 virtual users, and within 90 seconds you're seeing 429s. Stripe's test mode has rate limits. Your load test is testing Stripe's throttling, not your application.
You could spin up a local mock server. But your load test is running from CI, distributed across multiple workers. A local server isn't an option. WireMock Cloud works, but it's designed for developer testing, not 10k VUs — you'll see it fall over before your app does.
Here's how to mock Stripe's API on edge infrastructure that was built for this.
What You'll Need
- A Mockra account (free tier works — 5,000 requests/month)
- k6 installed locally or a k6 Cloud account
- 10 minutes
Step 1: Get Stripe's OpenAPI Spec
Stripe publishes their complete OpenAPI spec publicly on GitHub.
# Download Stripe's OpenAPI spec
curl -o stripe-openapi.yaml \
https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.yaml
The full Stripe spec is large — thousands of endpoints. Mockra will parse the whole spec, but you only need to configure the endpoints your load test will actually hit.
Step 2: Upload to Mockra
Via the dashboard:
- Go to dash.mockra.io
- Create a workspace (e.g., "Stripe Load Test")
- Upload the
stripe-openapi.yamlfile - Mockra parses all endpoints and auto-generates mock responses
After upload, mock endpoints are immediately live at mock.mockra.io/your-namespace/*.
Via the API (for CI/CD automation):
# Upload via API (using your API key)
curl -X POST https://api.mockra.io/workspaces/YOUR_WORKSPACE_ID/schemas \
-H "Authorization: Bearer mra_your_api_key" \
-F "file=@stripe-openapi.yaml"
Step 3: Configure the Endpoints You Care About
Don't configure all 500+ Stripe endpoints — just the ones your load test will hit. For a checkout flow, these are the three you need:
| Stripe Endpoint | Mock URL |
|---|---|
POST /v1/payment_intents |
mock.mockra.io/stripe-demo/v1/payment_intents |
POST /v1/payment_intents/{id}/confirm |
mock.mockra.io/stripe-demo/v1/payment_intents/{id}/confirm |
GET /v1/customers/{id} |
mock.mockra.io/stripe-demo/v1/customers/{id} |
In the dashboard, click on POST /v1/payment_intents and set the response body:
{
"id": "pi_mock_3MtwBwLkdIwHu7ix28a3tqPa",
"object": "payment_intent",
"amount": 2000,
"currency": "usd",
"status": "requires_payment_method",
"client_secret": "pi_mock_secret_3MtwBwLkdIwHu7ix28a3tqPa"
}
Set the status code to 200 and save. Repeat for the confirm and customer endpoints.
Step 4: Write the k6 Test
This script mirrors a real two-step checkout: create a payment intent, then confirm it.
// stripe-checkout-load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
// Replace with your Mockra namespace
const MOCK_BASE = 'https://mock.mockra.io/stripe-demo';
export const options = {
stages: [
{ duration: '2m', target: 100 }, // Ramp to 100 VUs
{ duration: '5m', target: 1000 }, // Ramp to 1,000 VUs
{ duration: '5m', target: 1000 }, // Hold at 1,000 VUs
{ duration: '2m', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<100'], // 95% of requests under 100ms
http_req_failed: ['rate<0.01'], // Less than 1% error rate
},
};
export default function () {
// Step 1: Create a payment intent
const createRes = http.post(
`${MOCK_BASE}/v1/payment_intents`,
JSON.stringify({ amount: 2000, currency: 'usd' }),
{ headers: { 'Content-Type': 'application/json' } }
);
check(createRes, {
'payment intent created': (r) => r.status === 200,
'has payment intent id': (r) => r.json('id') !== null,
});
const paymentIntentId = createRes.json('id');
// Step 2: Confirm the payment intent
const confirmRes = http.post(
`${MOCK_BASE}/v1/payment_intents/${paymentIntentId}/confirm`,
JSON.stringify({ payment_method: 'pm_card_visa' }),
{ headers: { 'Content-Type': 'application/json' } }
);
check(confirmRes, {
'payment confirmed': (r) => r.status === 200,
});
sleep(1);
}
Key things to note:
stagesramps from 0 to 1,000 VUs over 14 minutesthresholdsfail the test if P95 exceeds 100ms or error rate exceeds 1%- The script simulates a real two-step checkout: create intent → confirm
Step 5: Run the Test
k6 run stripe-checkout-load-test.js
Representative output:
/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io
execution: local
script: stripe-checkout-load-test.js
output: -
scenarios: (100.00%) 1 scenario, 1000 max VUs, 14m30s max duration
✓ payment intent created
✓ has payment intent id
✓ payment confirmed
checks.........................: 100.00% ✓ 1200000 ✗ 0
http_req_duration..............: avg=8ms p(95)=18ms p(99)=31ms
http_req_failed................: 0.00% ✓ 0 ✗ 600000
http_reqs......................: 600000 714.28/s
The P95 of 18ms is the mock server's response time. Your actual application performance numbers go in place of this variable — the mock removes the third-party API from the equation entirely.
Testing Failure Scenarios
This is where Mockra pulls ahead of Stripe's sandbox: you can force specific failure modes on demand.
Configure POST /v1/payment_intents/{id}/confirm to return a 402 with this body:
{
"error": {
"code": "card_declined",
"decline_code": "insufficient_funds",
"message": "Your card has insufficient funds.",
"type": "card_error"
}
}
Now load test your error handling path — the card_declined branch — at 1,000 VUs. Stripe's sandbox can't return failures on demand at scale. Mockra can.
Going Further: Stateful Checkout Flows
The examples above use static mock responses — every request to POST /v1/payment_intents returns the same body. That works for most load tests.
For flows where state matters across sequential calls — a payment intent that transitions from requires_payment_method to succeeded — Mockra supports stateful mocks. Each endpoint can cycle through a sequence of responses, tracked atomically across all concurrent virtual users.
See the stateful OAuth guide for a full walkthrough of the state sequence model.
Wrap-Up
Mockra is free for 5,000 requests/month — enough to validate this setup before running a full load test. The Stripe OpenAPI spec is public and works out of the box.
Questions or issues? The raw k6 scripts from this tutorial are in the mockra-io/benchmarks GitHub repo.
Try Mockra free
5,000 requests/month, no credit card required. Upload an OpenAPI spec and get mock endpoints in under 60 seconds.