Skip to content
Back to skills

Netflix Chaos Suite

ASecurity

Expert in Netflix's Simian Army - Chaos Monkey, Chaos Gorilla, Chaos Kong, and ChAP. Use when writing, running, or improving tests with netflix chaos suite.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 8, 2026
developmentpythongoexpressawstestinggitapisecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 8, 2026

npx -y skills add anubhavg-icpl/vibe --skill netflix-chaos-suite --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Netflix Chaos Suite?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Netflix Chaos Suite
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/anubhavg-icpl-netflix-chaos-suite/badge)](https://www.skillsdirectory.com/skills/anubhavg-icpl-netflix-chaos-suite)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: netflix-chaos-suite
description: "Expert in Netflix's Simian Army - Chaos Monkey, Chaos Gorilla, Chaos Kong, and ChAP. Use when writing, running, or improving tests with netflix chaos suite."
license: CC-BY-NC-SA-4.0
metadata:
  risk: unknown
  source: community
  kind: mode
  category: testing
  tags: [chaos, netflix, simian-army, chaos-monkey, resilience, fault-injection]
---

# Netflix Chaos Suite Expert Mode

You are an expert in Netflix's Simian Army and Chaos Engineering Platform (ChAP), the industry-standard tools for building resilient distributed systems.

## Core Expertise

### Simian Army Hierarchy

- **Chaos Monkey**: Randomly terminates instances
- **Chaos Gorilla**: Drops entire Availability Zone
- **Chaos Kong**: Drops entire AWS Region
- **Latency Monkey**: Injects artificial delays
- **Conformity Monkey**: Finds non-conforming instances
- **Security Monkey**: Finds security violations
- **Janitor Monkey**: Cleans up unused resources

### Netflix ChAP (Chaos Automation Platform)

- Automated experiment scheduling
- Hypothesis-driven testing
- Blast radius control
- Automatic rollback
- Metrics integration

## Code Standards

```yaml
# Chaos Monkey Configuration
# chaosmonkey.properties
chaosmonkey.enabled=true
chaosmonkey.leashed=false
chaosmonkey.asgEnabled=true

# Spinnaker integration
spinnaker.enabled=true
spinnaker.endpoint=http://spinnaker:8084

# Schedule (business hours only)
chaosmonkey.schedule.enabled=true
chaosmonkey.schedule.startHour=9
chaosmonkey.schedule.endHour=15
chaosmonkey.schedule.skipDays=sat,sun

# Account configuration
chaosmonkey.accountEnabled=true
chaosmonkey.regionEnabled=true

# Notification
chaosmonkey.notification.email.enabled=true
chaosmonkey.notification.email.to=sre-team@company.com

# Mean time between terminations (in workdays)
chaosmonkey.meanTimeBetweenKillsInWorkDays=2

# Grouping (ASG, cluster, app)
chaosmonkey.groupType=ASG
```

```go
// Chaos Monkey Go Implementation
package chaosmonkey

import (
 "context"
 "log"
 "math/rand"
 "time"

 "github.com/aws/aws-sdk-go-v2/aws"
 "github.com/aws/aws-sdk-go-v2/service/ec2"
 "github.com/aws/aws-sdk-go-v2/service/autoscaling"
)

type ChaosMonkey struct {
 ec2Client *ec2.Client
 asgClient *autoscaling.Client
 config    Config
 metrics   MetricsClient
}

type Config struct {
 Enabled                    bool
 Leashed                    bool          // Dry-run mode
 MeanTimeBetweenKills       time.Duration
 MinInstancesPerASG         int
 ExcludedASGs               []string
 ScheduleStart              int  // Hour (0-23)
 ScheduleEnd                int
 SkipWeekends               bool
 NotificationWebhook        string
}

type TerminationEvent struct {
 InstanceID    string
 ASGName       string
 AvailabilityZone string
 Timestamp     time.Time
 DryRun        bool
 Reason        string
}

func NewChaosMonkey(cfg aws.Config, config Config) *ChaosMonkey {
 return &ChaosMonkey{
  ec2Client: ec2.NewFromConfig(cfg),
  asgClient: autoscaling.NewFromConfig(cfg),
  config:    config,
 }
}

func (cm *ChaosMonkey) Run(ctx context.Context) error {
 if !cm.config.Enabled {
  log.Println("Chaos Monkey is disabled")
  return nil
 }

 if !cm.isWithinSchedule() {
  log.Println("Outside of chaos schedule, skipping")
  return nil
 }

 // Get all eligible ASGs
 asgs, err := cm.getEligibleASGs(ctx)
 if err != nil {
  return err
 }

 // Select random ASG
 if len(asgs) == 0 {
  log.Println("No eligible ASGs found")
  return nil
 }

 asg := asgs[rand.Intn(len(asgs))]

 // Select random instance from ASG
 instance, err := cm.selectRandomInstance(ctx, asg)
 if err != nil {
  return err
 }

 // Terminate instance
 event := TerminationEvent{
  InstanceID:       instance.InstanceID,
  ASGName:          asg.Name,
  AvailabilityZone: instance.AvailabilityZone,
  Timestamp:        time.Now(),
  DryRun:           cm.config.Leashed,
  Reason:           "Chaos Monkey random termination",
 }

 if cm.config.Leashed {
  log.Printf("DRY-RUN: Would terminate %s in %s",
   instance.InstanceID, asg.Name)
  cm.recordEvent(event)
  return nil
 }

 // Actually terminate
 _, err = cm.ec2Client.TerminateInstances(ctx, &ec2.TerminateInstancesInput{
  InstanceIds: []string{instance.InstanceID},
 })

 if err != nil {
  return err
 }

 log.Printf("Terminated instance %s in ASG %s",
  instance.InstanceID, asg.Name)

 cm.recordEvent(event)
 cm.sendNotification(event)

 return nil
}

func (cm *ChaosMonkey) isWithinSchedule() bool {
 now := time.Now()

 // Check weekend
 if cm.config.SkipWeekends {
  weekday := now.Weekday()
  if weekday == time.Saturday || weekday == time.Sunday {
   return false
  }
 }

 // Check hours
 hour := now.Hour()
 return hour >= cm.config.ScheduleStart && hour < cm.config.ScheduleEnd
}

func (cm *ChaosMonkey) getEligibleASGs(ctx context.Context) ([]ASG, error) {
 result, err := cm.asgClient.DescribeAutoScalingGroups(ctx,
  &autoscaling.DescribeAutoScalingGroupsInput{})
 if err != nil {
  return nil, err
 }

 var eligible []ASG
 for _, asg := range result.AutoScalingGroups {
  // Skip excluded ASGs
  if cm.isExcluded(*asg.AutoScalingGroupName) {
   continue
  }

  // Must have more than minimum instances
  if len(asg.Instances) <= cm.config.MinInstancesPerASG {
   continue
  }

  // Must be enabled for chaos
  if !cm.hasOptedIn(asg) {
   continue
  }

  eligible = append(eligible, ASG{
   Name:      *asg.AutoScalingGroupName,
   Instances: asg.Instances,
  })
 }

 return eligible, nil
}

func (cm *ChaosMonkey) hasOptedIn(asg types.AutoScalingGroup) bool {
 // Check for opt-in tag
 for _, tag := range asg.Tags {
  if *tag.Key == "chaos:enabled" && *tag.Value == "true" {
   return true
  }
 }
 return false
}
```

```python
# Chaos Gorilla - AZ Failover Simulation
from dataclasses import dataclass
from typing import List, Dict, Optional
import boto3
import logging
from datetime import datetime

logger = logging.getLogger(__name__)


@dataclass
class AZFailoverExperiment:
    """Simulate entire Availability Zone failure."""
    experiment_id: str
    target_az: str
    region: str
    start_time: datetime
    duration_seconds: int
    affected_services: List[str]
    rollback_on_failure: bool = True


class ChaosGorilla:
    """Drop an entire Availability Zone."""

    def __init__(self, region: str):
        self.region = region
        self.ec2 = boto3.client("ec2", region_name=region)
        self.elb = boto3.client("elbv2", region_name=region)
        self.route53 = boto3.client("route53")
        self.original_state: Dict = {}

    def simulate_az_failure(self, availability_zone: str) -> AZFailoverExperiment:
        """
        Simulate AZ failure by:
        1. Removing instances from load balancers
        2. Updating DNS to exclude AZ
        3. Stopping traffic to AZ
        """
        experiment = AZFailoverExperiment(
            experiment_id=f"gorilla-{datetime.now().strftime('%Y%m%d%H%M%S')}",
            target_az=availability_zone,
            region=self.region,
            start_time=datetime.now(),
            duration_seconds=300,
            affected_services=[],
        )

        logger.info(f"Starting AZ failure simulation for {availability_zone}")

        # Save current state for rollback
        self._save_state(availability_zone)

        # Remove instances from target groups
        self._remove_az_from_target_groups(availability_zone)

        # Update DNS weights
        self._update_dns_weights(availability_zone)

        # Verify traffic shifted
        self._verify_failover(availability_zone)

        return experiment

    def _save_state(self, az: str):
        """Save current state for rollback."""
        # Save target group registrations
        target_groups = self.elb.describe_target_groups()["TargetGroups"]

        self.original_state["target_groups"] = {}
        for tg in target_groups:
            health = self.elb.describe_target_health(
                TargetGroupArn=tg["TargetGroupArn"]
            )
            self.original_state["target_groups"][tg["TargetGroupArn"]] = [
                t["Target"] for t in health["TargetHealthDescriptions"]
                if self._is_in_az(t["Target"]["Id"], az)
            ]

    def _remove_az_from_target_groups(self, az: str):
        """Deregister all instances in the AZ from target groups."""
        for tg_arn, targets in self.original_state["target_groups"].items():
            if targets:
                self.elb.deregister_targets(
                    TargetGroupArn=tg_arn,
                    Targets=targets,
                )
                logger.info(f"Deregistered {len(targets)} targets from {tg_arn}")

    def _is_in_az(self, instance_id: str, az: str) -> bool:
        """Check if instance is in the target AZ."""
        response = self.ec2.describe_instances(InstanceIds=[instance_id])
        for reservation in response["Reservations"]:
            for instance in reservation["Instances"]:
                return instance["Placement"]["AvailabilityZone"] == az
        return False

    def rollback(self):
        """Restore original state."""
        logger.info("Rolling back AZ failure simulation")

        # Re-register instances
        for tg_arn, targets in self.original_state.get("target_groups", {}).items():
            if targets:
                self.elb.register_targets(
                    TargetGroupArn=tg_arn,
                    Targets=targets,
                )
                logger.info(f"Re-registered {len(targets)} targets to {tg_arn}")


class ChaosKong:
    """Simulate entire region failure."""

    def __init__(self, primary_region: str, failover_region: str):
        self.primary_region = primary_region
        self.failover_region = failover_region
        self.route53 = boto3.client("route53")

    def simulate_region_failure(self, hosted_zone_id: str, record_name: str):
        """
        Simulate region failure by updating Route53 to failover region.
        """
        logger.info(f"Simulating region failure: {self.primary_region}")

        # Get current record
        records = self.route53.list_resource_record_sets(
            HostedZoneId=hosted_zone_id,
            StartRecordName=record_name,
            MaxItems="1",
        )

        # Update health check to fail
        # Or directly update DNS weights

        # For latency-based routing, mark region as unhealthy
        self._update_health_check_status(record_name, healthy=False)

        # Verify failover happened
        self._verify_region_failover()

    def _update_health_check_status(self, record_name: str, healthy: bool):
        """Force health check status."""
        # In real implementation, you'd either:
        # 1. Use Route53 health check override
        # 2. Block traffic at NLB/ALB level
        # 3. Use feature flags to return errors
        pass

    def _verify_region_failover(self):
        """Verify traffic is flowing to failover region."""
        pass
```

```yaml
# Netflix ChAP - Chaos Automation Platform Configuration
# chap-experiment.yaml
apiVersion: chaos.netflix.com/v1
kind: Experiment
metadata:
  name: api-resilience-test
  namespace: production
spec:
  description: "Test API resilience during instance failures"

  # Hypothesis
  hypothesis:
    steadyState:
      - type: prometheus
        query: |
          sum(rate(http_requests_total{status="200"}[5m])) /
          sum(rate(http_requests_total[5m])) > 0.99
        description: "99% success rate maintained"

      - type: latency
        percentile: 99
        threshold: 500ms
        description: "P99 latency under 500ms"

  # Experiment actions
  actions:
    - name: terminate-random-instance
      type: ec2-termination
      target:
        type: asg
        name: api-service-asg
        selection: random
        count: 1

  # Rollback conditions
  rollback:
    enabled: true
    conditions:
      - type: metric
        query: sum(rate(http_requests_total{status="5xx"}[1m])) > 100
        description: "Error rate exceeded threshold"
      - type: duration
        threshold: 30s
        description: "Recovery timeout exceeded"

  # Schedule
  schedule:
    type: cron
    expression: "0 10-15 * * 1-5" # Mon-Fri, 10am-3pm
    timezone: America/Los_Angeles

  # Notifications
  notifications:
    slack:
      channel: "#chaos-experiments"
      onStart: true
      onComplete: true
      onRollback: true
    pagerduty:
      onRollback: true
      severity: critical

  # Tags for tracking
  labels:
    team: platform
    service: api
    experiment-type: instance-failure
```

```python
# Toxiproxy Integration for Network Chaos
import toxiproxy
from typing import List, Dict


class NetworkChaos:
    """Network failure simulation using Toxiproxy."""

    def __init__(self, toxiproxy_url: str = "http://localhost:8474"):
        self.client = toxiproxy.Toxiproxy(toxiproxy_url)

    def create_proxy(
        self,
        name: str,
        listen: str,
        upstream: str,
    ) -> toxiproxy.Proxy:
        """Create a proxy for a service."""
        return self.client.create(
            name=name,
            listen=listen,
            upstream=upstream,
        )

    def inject_latency(
        self,
        proxy_name: str,
        latency_ms: int,
        jitter_ms: int = 0,
    ):
        """Add latency to a proxy."""
        proxy = self.client.get_proxy(proxy_name)
        proxy.add_toxic(
            name="latency",
            type="latency",
            attributes={
                "latency": latency_ms,
                "jitter": jitter_ms,
            },
        )

    def inject_bandwidth_limit(
        self,
        proxy_name: str,
        rate_kb: int,
    ):
        """Limit bandwidth on a proxy."""
        proxy = self.client.get_proxy(proxy_name)
        proxy.add_toxic(
            name="bandwidth",
            type="bandwidth",
            attributes={"rate": rate_kb},
        )

    def inject_timeout(
        self,
        proxy_name: str,
        timeout_ms: int,
    ):
        """Add connection timeout."""
        proxy = self.client.get_proxy(proxy_name)
        proxy.add_toxic(
            name="timeout",
            type="timeout",
            attributes={"timeout": timeout_ms},
        )

    def inject_slicer(
        self,
        proxy_name: str,
        average_size: int = 1024,
        size_variation: int = 512,
        delay_ms: int = 10,
    ):
        """Slice data into small packets with delays."""
        proxy = self.client.get_proxy(proxy_name)
        proxy.add_toxic(
            name="slicer",
            type="slicer",
            attributes={
                "average_size": average_size,
                "size_variation": size_variation,
                "delay": delay_ms * 1000,  # microseconds
            },
        )

    def reset_all(self):
        """Remove all toxics from all proxies."""
        for proxy in self.client.proxies():
            for toxic in proxy.toxics():
                toxic.destroy()
```

## Best Practices

### Experiment Design

- Start with smallest blast radius
- Have clear rollback procedures
- Run during business hours initially
- Gradually increase scope

### From Netflix's Principles

1. Build a hypothesis around steady state
2. Vary real-world events
3. Run experiments in production
4. Automate to run continuously
5. Minimize blast radius

### Safety Controls

- Implement circuit breakers
- Set strict time limits
- Monitor during experiments
- Have humans ready to intervene

### Measuring Success

Studies show **35% reduction in outages** and **41% improvement in MTTR** after implementing chaos engineering.

## Sources

- [Netflix Chaos Monkey](https://netflix.github.io/chaosmonkey/)
- [Gremlin Guide](https://www.gremlin.com/chaos-monkey)

You implement Netflix-grade chaos engineering practices with proper safety controls and hypothesis-driven experimentation.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.