故障矩阵

Fault kinds

Every kind of fault the matrix can inject, what it simulates, and what it catches.

本页还没有中文版,下面是英文原文。

Every trial injects one fault. A fault is named by a label: what happens, then where it happens. For example, status 500 on POST api.stripe.com/v1/checkout/sessions.

Provider calls

Faults on a call your app makes to Stripe, Resend, Slack or another provider:

FaultWhat happensWhat it catches
status 500, status 503The provider fails.Errors shown as success, missing retries.
status 429The provider rate-limits the call.Retries that hammer the API, or none at all.
resetThe connection drops before the provider answers.Calls with no timeout or error handling.
reset-afterThe provider did the work, but the answer is lost.Retries that charge or send twice.
delay <ms>msThe answer is slow.Timeouts that are too short, or missing.

Each provider's error bodies match what its own SDK expects, so your app's error handling runs as it would in production.

On HTTP/2, as gRPC uses, a fault hits one call. A reset resets that call's stream, and the other calls on the same connection carry on.

Your app's own API

When your page calls your app's API with fetch(), as a single-page app does, the matrix can fault those calls too. Turn it on with pageCalls in the config's matrix:

danwo.config.ts · the page's own API calls
matrix: { pageCalls: true },

It's off by default, because most pages show an error when their own API fails rather than retrying, and a trial that ends on that error fails. Turn it on for an app built to retry its API calls or recover from a failed one:

FaultWhat happensWhat it catches
status 500The API fails before it acts.Pages that hang or show nothing.
resetThe connection drops before the API sees the call.Calls with no error handling.
reset-afterThe API did the work, but the page never heard.Pages that retry a write that acts twice.

These are calls to an app danwo started on this machine, at localhost or 127.0.0.1. Page loads, scripts and streams are left alone.

Model APIs

Calls to OpenAI, Anthropic and the other model APIs can also get answers that go wrong. These check what your app does when the model answers badly.

FaultWhat the model sends
refusala refusal instead of an answer
empty-completionan answer with no text
truncatedan answer cut off at the token limit
content-filteran answer stopped by the provider's filter
malformed-tool-calla tool call whose arguments don't parse
stream-cuta stream that stops halfway

Webhooks

Faults on a webhook a provider sends your app:

FaultWhat happensWhat it catches
duplicateThe same webhook arrives twice.Work done twice, such as credits granted twice.
delay 600000msIt arrives ten minutes late.Pages that assume the webhook came first.
forgedA webhook arrives with a bad signature.Handlers that skip the signature check.
stale 3600sA correctly signed webhook from an hour ago.Handlers that accept replayed requests.

Races

Faults on timing, planned only where they can happen:

FaultWhat happens
double-submit on POST /buyA form or request is sent twice at once.
webhooks before redirectThe provider's webhooks arrive before the browser returns to your app.
reorder webhooks a, bTwo webhooks arrive the other way round.
slow-then-retryA payment call is slow; your app retries while the first one still succeeds.
2 concurrent usersThe whole test runs as two users at once. Ask for it with { concurrent: 2 }.

Database and cache

With danwo's data proxies in front of your app's Postgres and Redis, the matrix also faults the statements your test caused:

FaultWhat happens
reset-after on COMMITThe database committed, but your app never heard back.
serialization_failure, deadlockPostgres asks your app to retry the transaction.
down 3000msThe database is unreachable for three seconds.
OOM, READONLYRedis refuses a write.

See Database and cache to set this up.

Sockets and background jobs

FaultWhat happens
upgrade refused on WS …A WebSocket can't connect.
connection dropped on WS …A connected WebSocket drops.
status 500 on POST inngest.danwo.test/e/…A background job's event can't be sent.

Time

Faults don't move the clock. To test a trial that ends tomorrow or a token that expires, jump time forward inside the test. See Time travel.

Next

本页内容

在每个 Pull Request 上运行

每个 Pull Request 一个 GitHub Check 和一条评论,并附上完整的运行记录。

配置 CI