Photo by Teng Yuhong on Unsplash
To check whether ECS Container Insights is enabled, list your clusters with ListClusters, call DescribeClusters with include: ["SETTINGS"], and read the containerInsights setting: disabled, enabled (standard) or enhanced. ListAccountSettings shows the default that new clusters get. Changing it on an existing cluster takes one UpdateClusterSettings call.
Container Insights is the difference between “the service is slow” and “task 7 of the orders service has been at 98% memory since the last deploy”. Without it, the default AWS/ECS metrics stop at the cluster and service level, so when one task misbehaves you are guessing. It’s also easy to have ECS Container Insights enabled on the cluster you built by hand and disabled on the three that Terraform created later. Standalone jobs benefit as well: when a task started with ECS RunTask from AWS SDK v3 runs slower than expected, task-level CPU and memory metrics show why.
This example is for platform engineers who want a quick inventory: which clusters have it, which mode, what the account default is, and what turning it on will cost. The TypeScript script uses the AWS SDK for JavaScript v3, reports by default, and only changes clusters you name with --apply --names. It’s one of our AWS SDK v3 audit and cleanup scripts.
What do disabled, enabled and enhanced mean?
The containerInsights cluster setting accepts three values:
disabled: no Container Insights metrics or performance logs.enabled: standard Container Insights. Cluster, service and task-level metrics, collected from performance log events.enhanced: Container Insights with enhanced observability. Everything in standard plus task and container-level metrics and more dimensions, for both EC2 and Fargate. AWS’s setup guide recommends it over standard.
A value set on the cluster overrides the account setting. The account setting (PutAccountSetting with name containerInsights) only decides what new clusters get, so flipping the account default does nothing for clusters that already exist. That’s why an account with the default set to enhanced can still have old clusters at disabled, and why the script reports both.
If you run tasks on EC2 container instances, AWS requires ECS agent version 1.29 or later for Container Insights. Metrics land in the ECS/ContainerInsights namespace, and the performance log events go to /aws/ecs/containerinsights/<cluster>/performance.
What does Container Insights cost?
The two modes are priced differently. Standard mode bills its metrics as CloudWatch custom metrics plus the log ingestion behind them; enhanced mode has its own per-metric price that includes log ingestion (log storage is billed separately).
| US East (N. Virginia) | Standard (enabled) |
Enhanced (enhanced) |
|---|---|---|
| Metric price | $0.30 per metric-month (first 10,000 metrics) | $0.07 per metric-month, prorated hourly |
| Log ingestion | $0.50 per GB | Included in the metric price |
| Metrics per resource (Fargate) | 13 per cluster, 15 per service, 10 per task | 29 per cluster, 31 per service, 26 per task definition, 26 per task, 26 per container |
Prices as of September 2026, from the AWS Price List API (publication dated 22 September 2026) and the metric counts on the Amazon CloudWatch pricing page. Clusters on EC2 report slightly fewer standard metrics (11, 13 and 8).
Worked example, using the sizing from the pricing page: one Fargate cluster with 5 services and 50 running containers. The standard example counts 10 tasks; the enhanced example counts 10 task definitions running 20 tasks.
- Standard: 13 + (5 × 15) + (10 × 10) = 188 metrics × $0.30 = $56.40, plus about 3.02 GB of performance logs × $0.50 = $1.51. Total $57.91 a month.
- Enhanced: 29 + (5 × 31) + (10 × 26) + (20 × 26) + (50 × 26) = 2,264 metrics × $0.07 = $158.48 a month.
Containers dominate the enhanced bill, so a cluster with many small sidecar containers costs more than its task count suggests. Turn enhanced on where you debug often, and keep standard on quiet clusters. To see what CloudWatch already costs you, run the example to get this month’s AWS CloudWatch cost with Cost Explorer before and after.
What does the script do?
- Reads the account default
ListAccountSettingswithname: "containerInsights"andeffectiveSettings: truereturns what a new cluster created by this principal would get. - Lists clusters
paginateListClusterscollects every cluster ARN in the Region. - Describes them in batches of 100
DescribeClustersaccepts up to 100 clusters per call;include: ["SETTINGS"]adds thecontainerInsightsvalue. Without it, the settings aren’t returned. - ClassifiesA disabled cluster with active services or running tasks is flagged
OFF on a cluster with running work; an empty cluster is noted but not flagged. - Optionally appliesWith
--apply --names a,bit callsUpdateClusterSettingsfor those clusters only, with--value enhanced(default) orenabled.
Prerequisites
- Node.js 18 or later,
tsx, and@aws-sdk/client-ecs. The guide to paginate any AWS API with AWS SDK v3 paginators explainspaginateListClusters. - An AWS profile with the permissions below. Run the report with a read-only profile and apply with a separate one.
- If your Container Insights logs use a customer managed KMS key, its key policy must allow CloudWatch Logs; the example to find CloudWatch log groups without KMS encryption shows how to check the performance log group.
Which IAM permissions does it need?
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListClustersAndDefaults",
"Effect": "Allow",
"Action": ["ecs:ListClusters", "ecs:ListAccountSettings"],
"Resource": "*"
},
{
"Sid": "DescribeClusters",
"Effect": "Allow",
"Action": "ecs:DescribeClusters",
"Resource": "arn:aws:ecs:*:111122223333:cluster/*"
},
{
"Sid": "ApplyOnlyToNamedClusters",
"Effect": "Allow",
"Action": "ecs:UpdateClusterSettings",
"Resource": "arn:aws:ecs:us-east-1:111122223333:cluster/orders"
}
]
}
ecs:ListClusters and ecs:ListAccountSettings don’t support resource-level permissions. Drop the third statement for report-only runs. The IAM policy generator for TypeScript code drafts a policy if you extend the script.
The script to check whether ECS Container Insights is enabled
// check-ecs-container-insights.ts
// Lists every ECS cluster in a Region with its containerInsights setting (disabled, enabled or enhanced),
// its service and task counts, and the account default that new clusters get. Report only, unless you pass
// --apply with an explicit list of cluster names.
// Usage: npx tsx check-ecs-container-insights.ts [--region us-east-1]
// npx tsx check-ecs-container-insights.ts --apply --names orders,payments [--value enhanced|enabled]
import {
DescribeClustersCommand,
ECSClient,
ListAccountSettingsCommand,
UpdateClusterSettingsCommand,
paginateListClusters,
type Cluster,
} from "@aws-sdk/client-ecs";
const args = process.argv.slice(2);
const flag = (name: string): string | undefined => {
const i = args.indexOf(name);
return i >= 0 ? args[i + 1] : undefined;
};
const region = flag("--region") ?? process.env.AWS_REGION ?? "us-east-1";
const apply = args.includes("--apply");
const names = (flag("--names") ?? "").split(",").map((s) => s.trim()).filter(Boolean);
const target = flag("--value") ?? "enhanced";
if (target !== "enhanced" && target !== "enabled") {
console.error("--value must be enhanced or enabled");
process.exit(1);
}
if (apply && names.length === 0) {
console.error("--apply needs --names cluster-a,cluster-b (the script never changes every cluster at once)");
process.exit(1);
}
const ecs = new ECSClient({ region });
const errText = (err: unknown): string => (err instanceof Error ? `${err.name}: ${err.message}` : String(err));
// The effective account default for the calling principal: what a new cluster gets if it sets nothing itself
async function accountDefault(): Promise<string> {
const out = await ecs.send(new ListAccountSettingsCommand({ name: "containerInsights", effectiveSettings: true }));
return out.settings?.[0]?.value ?? "not returned";
}
async function allClusters(): Promise<Cluster[]> {
const arns: string[] = [];
for await (const page of paginateListClusters({ client: ecs }, {})) arns.push(...(page.clusterArns ?? []));
const clusters: Cluster[] = [];
for (let i = 0; i < arns.length; i += 100) {
// DescribeClusters takes up to 100 clusters; SETTINGS adds the containerInsights value
const out = await ecs.send(new DescribeClustersCommand({ clusters: arns.slice(i, i + 100), include: ["SETTINGS"] }));
clusters.push(...(out.clusters ?? []));
for (const f of out.failures ?? []) console.error(`Could not describe ${f.arn}: ${f.reason}`);
}
return clusters;
}
const insightsOf = (c: Cluster): string =>
c.settings?.find((s) => s.name === "containerInsights")?.value ?? "not set";
function finding(c: Cluster): string {
const value = insightsOf(c);
const busy = (c.activeServicesCount ?? 0) + (c.runningTasksCount ?? 0) > 0;
if (value === "enhanced") return "enhanced: task and container metrics";
if (value === "enabled") return "standard: cluster, service and task metrics";
return busy ? "OFF on a cluster with running work" : "off (no services or tasks)";
}
async function applyChanges(): Promise<void> {
for (const name of names) {
try {
const out = await ecs.send(
new UpdateClusterSettingsCommand({ cluster: name, settings: [{ name: "containerInsights", value: target }] }),
);
console.log(`${name}: containerInsights is now ${out.cluster ? insightsOf(out.cluster) : "unknown"}`);
} catch (err) {
console.error(`${name}: ${errText(err)}`);
process.exitCode = 1;
}
}
}
async function main(): Promise<void> {
if (apply) return applyChanges();
const [defaultValue, clusters] = await Promise.all([accountDefault(), allClusters()]);
const rows = clusters.map((c) => ({
Cluster: c.clusterName ?? "?",
ContainerInsights: insightsOf(c),
Services: c.activeServicesCount ?? 0,
RunningTasks: c.runningTasksCount ?? 0,
Instances: c.registeredContainerInstancesCount ?? 0,
Finding: finding(c),
}));
rows.sort((a, b) => b.RunningTasks - a.RunningTasks);
console.table(rows);
const off = rows.filter((r) => r.Finding.startsWith("OFF")).length;
console.log(`Account default for new clusters in ${region}: containerInsights=${defaultValue}`);
console.log(`${rows.length} clusters: ${off} running work without Container Insights. Report only: nothing was changed.`);
}
main().catch((err) => {
console.error(errText(err));
process.exit(1);
});
How do you run it?
npm install @aws-sdk/client-ecs
npm install --save-dev tsx typescript @types/node
# Report
AWS_PROFILE=readonly npx tsx check-ecs-container-insights.ts --region us-east-1
# Turn on enhanced observability for two named clusters
AWS_PROFILE=platform-admin npx tsx check-ecs-container-insights.ts --region us-east-1 --apply --names orders,payments
Sample output
┌─────────┬──────────┬───────────────────┬──────────┬──────────────┬───────────┬────────────────────────────────────────┐
│ (index) │ Cluster │ ContainerInsights │ Services │ RunningTasks │ Instances │ Finding │
├─────────┼──────────┼───────────────────┼──────────┼──────────────┼───────────┼────────────────────────────────────────┤
│ 0 │ 'orders' │ 'disabled' │ 4 │ 12 │ 0 │ 'OFF on a cluster with running work' │
│ 1 │ 'batch' │ 'enhanced' │ 1 │ 3 │ 0 │ 'enhanced: task and container metrics' │
│ 2 │ 'dev' │ 'not set' │ 0 │ 0 │ 0 │ 'off (no services or tasks)' │
└─────────┴──────────┴───────────────────┴──────────┴──────────────┴───────────┴────────────────────────────────────────┘
Account default for new clusters in us-east-1: containerInsights=enabled
3 clusters: 1 running work without Container Insights. Report only: nothing was changed.
Cluster names and counts are illustrative (this output came from a run against mocked SDK clients). orders runs 12 tasks with no Container Insights at all, even though the account default is enabled: it was created before the default changed. dev has nothing running, so there’s nothing to monitor yet.
Troubleshooting
- The setting shows “not set”. The cluster has no explicit value in
settings. Set one with--applyso the cluster doesn’t depend on history. AccessDeniedExceptiononUpdateClusterSettings. The policy’s resource ARN must match the cluster’s Region and name. The walkthrough to troubleshoot AWS IAM access denied errors step by step covers the usual causes.- No metrics after enabling. Give it a few minutes, then check the
ECS/ContainerInsightsnamespace in the same Region. On EC2 capacity, check the agent version. - Log costs grow. The performance log group keeps data until you set a retention period. The script to set CloudWatch log retention for all log groups fixes that in one pass.
Ask ChatWithCloud instead
For a one-off check, ask ChatWithCloud “Which ECS clusters in us-east-1 have Container Insights disabled but running tasks?” It writes AWS SDK for JavaScript v2 code, runs it on your machine with your AWS profile and answers from the result; the ChatWithCloud question-to-SDK-code loop explains each step. It can be wrong, and it runs changes without a confirmation step, so use a read-only profile and apply settings with this script. The ChatWithCloud security model covers what leaves your machine.
Container Insights shows you what containers do; it doesn’t tell you whether they should run the way they do. Pair it with the scripts to find privileged ECS task definitions and root containers and find plaintext secrets in ECS task definitions. Once the metrics show which services sit idle most of the day, the example to find ECS services that could use Fargate Spot turns them into savings.
Frequently asked questions
How do I know if ECS Container Insights is enabled on a cluster?
Call DescribeClusters with include: ["SETTINGS"] and read the containerInsights value, or open the cluster in the ECS console. enabled means standard mode and enhanced means enhanced observability.
Does changing the account setting enable Container Insights on existing clusters?
No. The account setting only applies to clusters created afterwards. Use UpdateClusterSettings on each existing cluster.
Is enhanced observability more expensive than standard Container Insights?
Per metric it’s cheaper ($0.07 vs $0.30 in US East as of September 2026), but it reports many more metrics, including one set per container. In AWS’s example the enhanced bill is about 2.7 times the standard one.
Does Container Insights work on Fargate?
Yes. Both standard and enhanced modes support Fargate and EC2 launch types; EC2 container instances need ECS agent 1.29 or later.
Related guides
Ask your AWS account in plain English
Your first 15 runs are free, with no OpenAI key needed.
npx chatwithcloud