Skill 103 · AWS Fault Injection Service
Subchapter 103.5
references/fis-workflow.mdMarkdown10 KBView on GitHub
Follow this procedure to build, run, monitor, and analyze a FIS experiment. Consult fis-api-reference.md before writing any command and to choose actions/targets.
COUNT(1) / low PERCENT), pre-production
first. Only widen after it passes.The template needs a roleArn FIS assumes to perform actions. Create it with a trust policy for
fis.amazonaws.com and confused-deputy conditions, plus least-privilege permissions for the
target service APIs (and SSM / logs / report S3+CloudWatch if used). See
fis-security.md for the exact trust policy and permission examples.
An experiment template combines: description, roleArn, actions, targets,
stopConditions, optional logConfiguration, optional experimentReportConfiguration, optional
experimentOptions, and tags.
Scenarios are console-only. In the FIS console: Scenario library → pick a scenario → Create template with scenario → fill missing parameters, choose the service-access role, add stop conditions and logging → Create experiment template. To automate later, export the created template’s JSON. (See scenario list in fis-actions-reference.md.)
Build a JSON document and pass it to create-experiment-template. Minimal shape:
{
"description": "Reboot one prod EC2 instance; stop if error rate alarms",
"roleArn": "arn:aws:iam::123456789012:role/FISExperimentRole",
"actions": {
"RebootInstance": {
"actionId": "aws:ec2:reboot-instances",
"targets": { "Instances": "oneProdInstance" }
}
},
"targets": {
"oneProdInstance": {
"resourceType": "aws:ec2:instance",
"resourceTags": { "env": "prod" },
"selectionMode": "COUNT(1)"
}
},
"stopConditions": [
{ "source": "aws:cloudwatch:alarm",
"value": "arn:aws:cloudwatch:us-east-1:123456789012:alarm:HighErrorRate" }
],
"tags": { "Name": "reboot-one-prod-instance", "team": "checkout" }
}Create it:
aws fis create-experiment-template --cli-input-json file://template.json
stopConditionsis required in the template. Use[{"source":"none"}]only when you genuinely have no alarm — strongly discouraged for anything beyond a sandbox. Prefer a realaws:cloudwatch:alarmon your steady-state metric.
Actions run in parallel by default. To sequence, set startAfter to the names of prerequisite
actions. Use an aws:fis:wait action to insert a controlled pause (e.g., hold a fault for N
minutes before a follow-on action or before letting steady state recover).
A stop condition stops the experiment when a CloudWatch alarm enters ALARM. Base the alarm on the steady-state metric from step 0.
"stopConditions": [
{ "source": "aws:cloudwatch:alarm",
"value": "arn:aws:cloudwatch:us-east-1:123456789012:alarm:P99LatencyHigh" }
]You can specify multiple alarms (subject to the account quota). Alarm/dashboard creation itself belongs to the AWS Observability skill.
Capture per-experiment records (experiment-start, target-resolution-*, action-start/end/ error, experiment-end) to CloudWatch Logs and/or S3. logSchemaVersion must be 2.
FIS does not require logging, but without it there is no experiment-level audit trail beyond CloudTrail, which makes post-incident troubleshooting very difficult. Enable it for anything beyond a throwaway sandbox.
"logConfiguration": {
"logSchemaVersion": 2,
"cloudWatchLogsConfiguration": {
"logGroupArn": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/fis/experiments:*"
},
"s3Configuration": { "bucketName": "my-fis-logs", "prefix": "experiments" }
}Grant FIS the vended-logs delivery permissions for each destination. First run to a new
destination is delayed ~15 s to configure delivery. Logging is disabled by default; enable via
create-experiment-template or add later with update-experiment-template. Use logs (not the
report) to troubleshoot failed experiments.
Encrypt both destinations. Experiment logs reveal resilience posture and architectural weaknesses. Encrypt the CloudWatch Logs log group with a KMS key (
kmsKeyIdat creation, oraws logs associate-kms-key), and enable SSE-KMS on the S3 bucket with a bucket policy that denies non-TLS requests (aws:SecureTransport). See fis-security.md — Data handling.
Generate a PDF summarizing the experiment plus a CloudWatch dashboard snapshot, delivered to S3.
"experimentReportConfiguration": {
"outputs": { "s3Configuration": { "bucketName": "my-fis-reports", "prefix": "checkout" } },
"dataSources": {
"cloudWatchDashboards": [
{ "dashboardIdentifier": "arn:aws:cloudwatch::123456789012:dashboard/CheckoutHealth" }
]
},
"preExperimentDuration": "PT20M",
"postExperimentDuration": "PT20M"
}actionsMode: skip-all) runs.
preExperimentDuration and postExperimentDuration are ISO 8601 and default to 20 min each;
both are capped, as is the number of dashboards per report. Check the current values in the
FIS quotas documentation (opens in a new tab)
rather than assuming a fixed limit.aws:SecureTransport, the same way as the log
destinations above.cloudwatch:GetDashboard, cloudwatch:GetMetricWidgetImage,
s3:GetObject, s3:PutObject (+ kms:GenerateDataKey, kms:Decrypt for CMK-encrypted
buckets). Use the report only for successfully completed runs — troubleshoot failures with logs.experimentOptions on the template controls:
accountTargeting: single-account (default) or multi-account.emptyTargetResolutionMode: fail (default) or skip (don’t fail when a target resolves to
zero resources).actionsMode: run-all (normal) or skip-all (target preview — resolves targets without
running actions).Multi-account experiments run from an orchestrator account against resources in target
accounts (same Region). Set accountTargeting: multi-account, then add a target account
configuration per account (account ID + IAM role FIS assumes there + optional description):
aws fis create-target-account-configuration \
--experiment-template-id EXTxxxx --account-id 222233334444 \
--role-arn arn:aws:iam::222233334444:role/FISTargetAccountRole \
--description "checkout target account"Target accounts are notified via their AWS Health dashboards. Prefer consistent resource tags across accounts and target AZs by AZ ID. Per-account action quotas apply.
Generate a target preview (run with actionsMode: skip-all, or use the console/get-experiment
resolved-targets view) to confirm the exact resources that will be affected. This is the cheapest
way to catch an over-broad tag/filter before a real fault.
# Start
aws fis start-experiment --experiment-template-id EXTxxxx \
--tags Name=game-day-checkout
# Watch state
aws fis get-experiment --id EXPxxxx --query 'experiment.state'
# List which resources FIS actually selected
aws fis list-experiment-resolved-targets --id EXPxxxxStates: pending → initiating → running → completed | stopping → stopped | failed. Watch your
steady-state dashboard live. A stopped/failed experiment cannot be resumed.
aws fis stop-experiment --id EXPxxxxUse this if you observe unacceptable impact the stop-condition alarm didn’t catch. Afterward, consider tightening the alarm so the guardrail catches it automatically next time.
action-error reasons.aws-resilience-lifecycle).aws fis update-experiment-template --id EXTxxxx --cli-input-json file://template-v2.json
aws fis delete-experiment-template --id EXTxxxx # when retiringModel the template as AWS::FIS::ExperimentTemplate (and
AWS::FIS::TargetAccountConfiguration for multi-account) so experiments are version-controlled
and reviewed like other infrastructure. The property shape mirrors the CLI/JSON above.