Documentation Index Fetch the complete documentation index at: https://mintlify.com/visible/cruel/llms.txt
Use this file to discover all available pages before exploring further.
What are Scenarios?
Scenarios are time-based chaos patterns that simulate real-world incidents and failure conditions. Unlike static chaos injection, scenarios run for a specific duration and can model complex failure modes like network partitions, data center failovers, and traffic spikes.
Basic Usage
Define and play scenarios:
import { cruel } from 'cruel'
// Wrap your functions
const fetchData = cruel ( async () => { /* ... */ })
// Define a scenario
cruel . scenario ( 'network-outage' , {
chaos: { fail: 1 }, // 100% failure rate
duration: 5000 // Lasts 5 seconds
})
// Play the scenario
await cruel . play ( 'network-outage' )
// Scenario stops automatically after 5 seconds
// Or stop manually:
cruel . stop ()
Scenario API
cruel.scenario()
Define a reusable scenario:
cruel . scenario ( name : string , config : {
chaos? : ChaosOptions ,
duration? : number // In milliseconds
})
cruel.play()
Start a scenario:
await cruel . play ( 'scenario-name' )
// Returns after scenario duration completes
// Or without await for background execution
cruel . play ( 'scenario-name' ) // Runs in background
cruel.stop()
Manually stop the active scenario:
cruel . stop () // Disables chaos and clears active scenario
cruel.activeScenario()
Check which scenario is running:
const active = cruel . activeScenario ()
if ( active ) {
console . log ( `Currently running: ${ active } ` )
} else {
console . log ( 'No active scenario' )
}
Built-in Scenarios
Cruel includes 12 pre-configured scenarios for common failure modes:
networkPartition
Complete network failure:
await cruel . play ( 'networkPartition' )
// { fail: 1, duration: 5000 }
100% failure rate - All requests fail
5 second duration
Use case: Test network split-brain scenarios
highLatency
Severe latency spike:
await cruel . play ( 'highLatency' )
// { delay: [2000, 5000], duration: 10000 }
2-5 second delays
10 second duration
Use case: Test timeout handling and user experience degradation
degraded
Partial service degradation:
await cruel . play ( 'degraded' )
// { fail: 0.1, delay: [500, 1500], duration: 30000 }
10% failure rate
500-1500ms latency
30 second duration
Use case: Test graceful degradation under load
outage
Major service outage:
await cruel . play ( 'outage' )
// { fail: 1, timeout: 0.5, duration: 60000 }
100% failures and 50% timeouts
60 second duration
Use case: Test disaster recovery procedures
recovery
Post-incident recovery phase:
await cruel . play ( 'recovery' )
// { fail: 0.3, delay: [100, 500], duration: 15000 }
30% failure rate
100-500ms latency
15 second duration
Use case: Test system behavior during recovery
blackFriday
High traffic with intermittent issues:
await cruel . play ( 'blackFriday' )
// { delay: [1000, 3000], fail: 0.15, jitter: 1000, duration: 60000 }
1-3 second base latency
15% failure rate
0-1 second jitter
60 second duration
Use case: Test black friday / traffic spike scenarios
mobileNetwork
Unstable mobile connectivity:
await cruel . play ( 'mobileNetwork' )
// { delay: [500, 2000], fail: 0.2, timeout: 0.1, duration: 30000 }
500-2000ms latency
20% failures, 10% timeouts
30 second duration
Use case: Test mobile app resilience
datacenterFailover
Data center switching:
await cruel . play ( 'datacenterFailover' )
// { fail: 0.5, delay: [200, 800], duration: 20000 }
50% failure rate
200-800ms latency
20 second duration
Use case: Test multi-region failover logic
ddosAttack
DDoS-like overload:
await cruel . play ( 'ddosAttack' )
// { timeout: 0.4, delay: [2000, 10000], duration: 30000 }
40% timeouts
2-10 second delays
30 second duration
Use case: Test rate limiting and backpressure
coldStart
Serverless cold start delays:
await cruel . play ( 'coldStart' )
// { delay: [3000, 8000], duration: 10000 }
3-8 second delays
10 second duration
Use case: Test serverless initialization latency
gcPause
Garbage collection pauses:
await cruel . play ( 'gcPause' )
// { delay: [100, 500], spike: [500, 2000], duration: 15000 }
100-500ms base delay
500-2000ms occasional spikes
15 second duration
Use case: Test impact of GC pauses
connectionPool
Connection pool exhaustion:
await cruel . play ( 'connectionPool' )
// { fail: 0.3, timeout: 0.2, duration: 20000 }
30% failures, 20% timeouts
20 second duration
Use case: Test connection pool management
Creating Custom Scenarios
Simple Scenario
Complex Scenario
Infinite Scenario
import { cruel } from 'cruel'
cruel . scenario ( 'maintenance-window' , {
chaos: {
fail: 0.5 ,
delay: [ 1000 , 2000 ]
},
duration: 30000 // 30 seconds
})
await cruel . play ( 'maintenance-window' )
import { cruel } from 'cruel'
cruel . scenario ( 'multi-region-failure' , {
chaos: {
fail: 0.7 , // 70% failures
timeout: 0.2 , // 20% timeouts
delay: [ 2000 , 5000 ], // 2-5s latency
jitter: 1000 , // Extra variance
spike: [ 5000 , 10000 ] // Occasional huge delays
},
duration: 120000 // 2 minutes
})
await cruel . play ( 'multi-region-failure' )
import { cruel } from 'cruel'
// Scenario without duration runs indefinitely
cruel . scenario ( 'manual-chaos' , {
chaos: { fail: 0.2 , delay: 500 }
// No duration - must call cruel.stop() manually
})
cruel . play ( 'manual-chaos' ) // Don't await
// Do your testing...
await runTests ()
// Stop when done
cruel . stop ()
Scenario Chains
Sequence scenarios to simulate complex incidents:
import { cruel } from 'cruel'
// Simulate incident lifecycle
async function simulateIncident () {
console . log ( 'Incident start: Network partition' )
await cruel . play ( 'networkPartition' ) // 5s total outage
console . log ( 'Partial recovery: Degraded service' )
await cruel . play ( 'degraded' ) // 30s degraded
console . log ( 'Recovering: Stabilizing' )
await cruel . play ( 'recovery' ) // 15s recovery
console . log ( 'Incident resolved' )
}
await simulateIncident ()
Using Scenarios in Tests
import { describe , it , expect , beforeEach , afterEach } from 'vitest'
import { cruel } from 'cruel'
import { fetchUserData } from './api'
describe ( 'Resilience Tests' , () => {
beforeEach (() => {
// Wrap functions before each test
cruel ( fetchUserData )
})
afterEach (() => {
cruel . stop ()
cruel . reset ()
})
it ( 'handles network partition' , async () => {
await cruel . play ( 'networkPartition' )
// Should use cached data during partition
const result = await myApp . getUserData ()
expect ( result ). toBeTruthy ()
expect ( result . source ). toBe ( 'cache' )
})
it ( 'recovers from degraded service' , async () => {
await cruel . play ( 'degraded' )
// Should complete despite 10% failures
const results = await Promise . allSettled (
Array ( 100 ). fill ( 0 ). map (() => fetchUserData ())
)
const successful = results . filter ( r => r . status === 'fulfilled' )
expect ( successful . length ). toBeGreaterThan ( 80 )
})
})
Scenario Monitoring
Track scenario impact:
import { cruel } from 'cruel'
cruel . scenario ( 'test-chaos' , {
chaos: { fail: 0.2 , delay: [ 500 , 1500 ] },
duration: 30000
})
const before = cruel . stats ()
await cruel . play ( 'test-chaos' )
const after = cruel . stats ()
console . log ( 'Scenario Impact:' )
console . log ( `Total calls: ${ after . calls - before . calls } ` )
console . log ( `Failures: ${ after . failures - before . failures } ` )
console . log ( `Avg latency: ${ after . avg } ms` )
console . log ( `p95 latency: ${ after . p95 } ms` )
Background Scenarios
Run scenarios without blocking:
import { cruel } from 'cruel'
// Start scenario in background (no await)
cruel . play ( 'degraded' )
// Continue with other operations
await runTests ()
await collectMetrics ()
// Scenario runs in parallel for 30 seconds
// Then stops automatically
Dynamic Scenarios
Create scenarios programmatically:
import { cruel } from 'cruel'
function createLoadScenario ( load : 'low' | 'medium' | 'high' ) {
const configs = {
low: { fail: 0.05 , delay: [ 100 , 300 ] },
medium: { fail: 0.15 , delay: [ 300 , 1000 ] },
high: { fail: 0.3 , delay: [ 1000 , 3000 ] }
}
cruel . scenario ( `load- ${ load } ` , {
chaos: configs [ load ],
duration: 60000
})
}
createLoadScenario ( 'low' )
createLoadScenario ( 'medium' )
createLoadScenario ( 'high' )
await cruel . play ( 'load-high' )
Best Practices
Test incrementally: Start with mild scenarios and progress to severe ones.
Document results: Record which scenarios your system can handle and which cause failures.
Automate: Run scenarios in CI/CD to catch resilience regressions.
Duration matters: Longer scenarios reveal issues that short bursts might miss.
Scenario Comparison
Scenario Failure % Timeout % Max Delay Duration Severity degraded 10% 0% 1.5s 30s Low mobileNetwork 20% 10% 2s 30s Medium datacenterFailover 50% 0% 0.8s 20s Medium ddosAttack 0% 40% 10s 30s High outage 100% 50% - 60s Critical networkPartition 100% 0% - 5s Critical
Next Steps
Chaos Injection Learn about the underlying chaos mechanics
Presets Use pre-configured chaos profiles
Statistics Track chaos impact with detailed metrics
Testing Guide Integrate scenarios into your test suite