2026-03-10 00:00:00 -07:00
# Chaos Mode
Inject controlled failures into contract tests to validate resilience guarantees.
2026-05-21 20:39:36 -07:00
Chaos testing applies invariant-driven verification under adverse conditions: if a contract must hold, it should still hold when dependencies fail, responses are delayed, or payloads are corrupted.
2026-03-10 00:00:00 -07:00
2026-03-10 00:00:00 -07:00
## Usage
2026-03-10 00:00:00 -07:00
``` javascript
2026-03-10 00:00:00 -07:00
const result = await fastify . apophis . contract ( {
2026-03-10 00:00:00 -07:00
runs : 50 ,
2026-03-10 00:00:00 -07:00
chaos : {
2026-03-10 00:00:00 -07:00
delay : { probability : 0.1 , minMs : 100 , maxMs : 500 } ,
error : { probability : 0.1 , statusCode : 503 } ,
dropout : { probability : 0.05 } ,
corruption : { probability : 0.1 } ,
2026-03-10 00:00:00 -07:00
} ,
2026-03-10 00:00:00 -07:00
} ) ;
2026-03-10 00:00:00 -07:00
```
## Event Types
### Delay
Adds artificial latency. Tests timeout contracts:
``` apostl
response_time(this) < 1000
```
2026-05-22 17:07:12 -07:00
Delay chaos strategies (`inbound-delay` , `outbound-delay` ) are applied at the transport level between request execution and contract evaluation. The inline chaos handlers for these strategies are no-ops because `sleep()` handles delay application out-of-band. Delay contracts such as `response_time(this) < 1000` will still work correctly with chaos injection.
2026-03-10 00:00:00 -07:00
2026-03-10 00:00:00 -07:00
### Error
Forces HTTP status codes. Tests error-handling contracts:
``` apostl
2026-03-10 00:00:00 -07:00
// Behavioral: when the service is unavailable, the client receives a valid retry signal
if status:503 then response_headers(this).retry-after > 0
2026-03-10 00:00:00 -07:00
```
### Dropout
Simulates network failure (status 0). Tests fallback contracts:
``` apostl
2026-03-10 00:00:00 -07:00
// Behavioral: partial failure must still return previously cached data
if status:0 then response_body(this).cached_data == previous(response_body(GET /cache/{request_params(this).key}))
2026-03-10 00:00:00 -07:00
```
### Corruption
Mutates response bodies. Tests parsing robustness:
``` apostl
2026-03-10 00:00:00 -07:00
// Behavioral: corrupted requests maintain traceability for debugging
if status:400 then response_body(this).request_id == request_headers(this).x-request-id
2026-03-10 00:00:00 -07:00
```
2026-03-10 00:00:00 -07:00
## Corruption Strategies
2026-03-10 00:00:00 -07:00
2026-03-10 00:00:00 -07:00
Built-in strategies are content-type agnostic:
2026-03-10 00:00:00 -07:00
2026-03-10 00:00:00 -07:00
| Strategy | Effect |
|----------|--------|
| `truncate` | Cuts response body short |
| `malformed` | Invalidates structural boundaries (e.g., unclosed JSON, bad headers) |
| `field-corrupt` | Replaces a random field value with corrupted data |
Extension strategies can add content-type-specific behavior if needed.
2026-03-10 00:00:00 -07:00
2026-05-22 17:07:12 -07:00
**Note ** : Extension-defined corruption strategies are documented for future implementation. Currently, corruption strategies (`truncate` , `malformed` , `field-corrupt` ) are hardcoded in the chaos engine.
2026-03-10 00:00:00 -07:00
## Environment Guard
Low-level contract chaos APIs require `NODE_ENV=test` . For CLI qualification, environment policy controls whether chaos gates may run.
```
2026-03-10 00:00:00 -07:00
Error: chaos is only available in test environment. Set NODE_ENV=test to enable quality features.
2026-03-10 00:00:00 -07:00
```
## Interpreting Results
Failed tests include chaos events in diagnostics:
``` json
{
"statusCode" : 503 ,
2026-03-10 00:00:00 -07:00
"error" : "Contract violation: if status:503 then response_headers(this).retry-after > 0" ,
2026-03-10 00:00:00 -07:00
"chaosEvents" : [
{
"type" : "error" ,
"injected" : true ,
"details" : {
"statusCode" : 503 ,
"reason" : "Chaos error: overridden 200 with 503"
}
}
]
}
```
## Best Practices
1. **Start small ** : `probability: 0.05` (5% of requests)
2. **Test one failure mode at a time ** : Comment out other chaos types
2026-03-10 00:00:00 -07:00
3. **Verify contracts handle chaos ** : `if status:503 then response_code(GET /health) == 200`
2026-03-10 00:00:00 -07:00
4. **Use seeds for reproducibility ** : `seed: 42` makes chaos deterministic
## Example: Testing Retry Logic
2026-03-10 00:00:00 -07:00
``` javascript
2026-03-10 00:00:00 -07:00
fastify . get ( '/data' , {
schema : {
'x-ensures' : [
2026-03-10 00:00:00 -07:00
'if status:503 then response_headers(this).retry-after > 0' ,
2026-03-10 00:00:00 -07:00
'redirect_count(this) <= 3' ,
] ,
} ,
2026-03-10 00:00:00 -07:00
} , handler ) ;
2026-03-10 00:00:00 -07:00
// Test
const result = await fastify . apophis . contract ( {
chaos : {
2026-03-10 00:00:00 -07:00
error : { probability : 0.2 , statusCode : 503 } ,
2026-03-10 00:00:00 -07:00
} ,
2026-03-10 00:00:00 -07:00
} ) ;
2026-03-10 00:00:00 -07:00
```