93 / 95 · 05 Performance & Chaos Engineering · Kubernetes Scaling and Container Performance Testing← prev⊞ allnext →☰ Read as one page
14.5Testing Cascading Failures in Microservices
In a microservices architecture, a slow downstream service can cause cascading failures upstream. Test this scenario explicitly:
// k6-cascading-failure-test.js
// Test: What happens when the payment service is slow?
import http from 'k6/http';
import { check } from 'k6';
import { Trend, Rate } from 'k6/metrics';
const orderLatency = new Trend('order_creation_latency', true);
const cascadeErrorRate = new Rate('cascade_errors');
export const options = {
scenarios: {
normal_traffic: {
executor: 'constant-arrival-rate',
rate: 50,
timeUnit: '1s',
duration: '10m',
preAllocatedVUs: 50,
maxVUs: 200,
},
},
thresholds: {
order_creation_latency: ['p(95)<5000'], // total order flow under 5s
cascade_errors: ['rate<0.1'], // under 10% cascade errors
},
};
export default function () {
// This test runs against the order service while separately
// injecting latency into the payment service (via Litmus/Chaos Mesh)
const res = http.post('https://staging.example.com/api/orders',
JSON.stringify({
items: [{ sku: "TEST-1", qty: 1 }],
payment: { method: "card", token: "tok_test" },
}),
{ headers: { 'Content-Type': 'application/json' }, timeout: '30s' }
);
orderLatency.add(res.timings.duration);
check(res, {
'order created or gracefully degraded': (r) =>
r.status === 201 || r.status === 202 || r.status === 503,
'no 500 internal errors': (r) => r.status !== 500,
});
// A 503 with a retry-after header is acceptable (circuit breaker open)
// A 500 is a cascading failure bug
cascadeErrorRate.add(res.status === 500);
}
Run this k6 test simultaneously with a Litmus network-latency experiment on the payment service to validate that circuit breakers, timeouts, and fallback logic work correctly.