Fault injection
Two request headers turn any route into a misbehaving upstream, so retry, timeout,
circuit breaker and failover policies can be shown against the endpoint you were
already demoing. They work on every route except the control plane
(/_rustybin/*) and the web console (/ui/*).
| Header | Effect |
|---|---|
X-Rustybin-Delay: <ms> | Wait that many milliseconds before handling the request (capped at 30000, 10000 in public mode). |
X-Rustybin-Fail: <status> | Answer with that status (400 to 599) and a JSON error body instead of calling the route. |
X-Rustybin-Fail: <status>:<percent> | The same with a probability: 503:50 fails about half of the requests (503:50% works too). |
Responses that were affected carry X-Rustybin-Fault: fail or
X-Rustybin-Fault: delay. Values that do not parse (a status outside 400 to 599, a
percent above 100, a negative delay) are ignored and the request is served
normally.
GET {{base_url}}/echo
X-Rustybin-Fail: 503
HTTP 503
[Asserts]
header "X-Rustybin-Fault" == "fail"
jsonpath "$.error" == "injected fault"
jsonpath "$.status" == 503
jsonpath "$.percent" == 100
jsonpath "$.injected_by" == "X-Rustybin-Fail"
# 0 percent never fails; 503:50 fails about half of the requests.
GET {{base_url}}/echo
X-Rustybin-Fail: 503:0
HTTP 200
POST {{base_url}}/anything/orders
X-Rustybin-Delay: 300
Content-Type: application/json
{"id": 1}
HTTP 200
[Asserts]
header "X-Rustybin-Fault" == "delay"
duration >= 300
Both headers combine: the delay happens first, then the fault.
GET {{base_url}}/status/200
X-Rustybin-Delay: 200
X-Rustybin-Fail: 504
HTTP 504
[Asserts]
duration >= 200
# Values that do not parse are ignored (the request is served normally).
GET {{base_url}}/echo
X-Rustybin-Fail: 200
HTTP 200
GET {{base_url}}/_rustybin/version
X-Rustybin-Fail: 500
HTTP 200
[Asserts]
jsonpath "$.name" == "rustybin"
On the mock LLM
On /ai/* the delay header works as above, but X-Rustybin-Fail is answered by the
mock LLM itself, in the provider's native error format (an OpenAI rate_limit_exceeded
body with x-ratelimit-* headers, an Anthropic 529 overloaded_error, a Gemini
RESOURCE_EXHAUSTED, ...), and accepts symbolic kinds such as rate_limit,
overloaded, context_length or content_filter. The mock LLM also has
X-Rustybin-Latency-Ms, X-Rustybin-TTFT-Ms and X-Rustybin-Tokens-Per-Second.
See Faults, latency, credentials, inspection.
Other chaos tools
| Tool | Use it for |
|---|---|
/status/{code} | A fixed or weighted random status (/status/200:0.9,503:0.1) |
/delay/{duration} | A slow endpoint (up to 60 s) without custom headers |
/drip | A slow body after fast headers (streaming timeouts) |
/flaky/* | Deterministic failure patterns per client: fail after n, recover after n, SSF patterns |
/health/unhealthy | Active health checks and failover (the gRPC health service follows it) |
gRPC Fail | Any gRPC status with rich error details |
RUSTYBIN_REQUEST_TIMEOUT | The server's own time-to-headers timeout (503) |