Controlled destruction for data pipelines
Reproducible attacks on your terms
Every attack is seeded, returns a copy of your DataFrame, never mutating the input, and reports exactly what changed and by how much.
Injects nulls into any column. The most common real failure, and your pipeline probably won't raise an exception.
Empty batches, large overflows, or truncated partials. See if your pipeline handles what it wasn't given.
Flips int to float, str to bool, object to numeric. The kind of breakage that survives ingestion.
Drops, renames, adds, or reorders columns, the way an upstream team deploys without telling you.
Pushes values N standard deviations beyond the distribution, the kind that wrecks an aggregation.
Out-of-order, late, future, missing windows, duplicate timestamps. Event-time logic is hard to get right.
Seed it, attack it, pass a health check: that's the whole API surface.
from havoc_monkey import HavocMonkey monkey = HavocMonkey(seed=42) # single attack, returns df.copy(), never mutates attacked = monkey.null_flood(df, cols=['amount'], pct=0.15) # campaign with health check def check(d): result = my_pipeline(d) assert result['amount'].notnull().all(), "nulls leaked" return True report = monkey.campaign( df, attacks=['null_flood', 'schema_drift', 'temporal'], health_check=check, ) print(report)