Heimdall ResearchSearch

What three Stripe SDKs retry under injected faults

Across 5 client configurations and 14 fault cells (70 combinations) no SDK retry made a second effect; the default Python client made 1 attempt in every cell and reported an error for a refund that existed.

MeasurementCompared with simpler mechanismsRe-checked

Designed for
Built to measure how many attempts, idempotency keys and effects the clients the guard sits behind (stripe-python, stripe-node, stripe-go) produce for one refund call under dropped, 500 and timeout faults.

What was tested

One create-refund call per cell ran against a fresh Stripe-shaped simulator in 14 fault cells, for five configurations of stripe-python 15.6.1, stripe-node 22.6.2 and stripe-go v86.4.2: 70 combinations. Attempts were counted from the provider ledger, with a control cell per configuration; two runs gave byte-identical tables. No language model ran.

What we observed

The default Python client made 1 attempt in all 14 cells; when the answer was dropped after the effect, it raised a connection error while the refund existed. The other four configurations retried a dropped answer under one key, so the caller saw success and one effect remained. stripe-go made 1 attempt on a 500 whatever the retry header said, and retried a timeout. No combination made more than one effect per call.

What this means for Heimdall

This asks what an existing alternative already gives. In this simulator, SDK retries under one idempotency key made no duplicate, so within one call the key keeps one effect; a duplicate needs a new key, which this study did not test. An error answer is no evidence that nothing happened.

Limits

A simulator, not the real API; non-JSON 5xx bodies unmeasured; the measured tree is not in this repository.

What remains open

Rerun the matrix on a current commit.