Batch transform jobs that ran on far more instance than they used
What does ZopNight detect here?
A finished transform job cannot be resized, so the advice targets its next run. ZopNight flags jobs whose per-vCPU CPU averaged under 10% with memory under 50%, names the concrete one-tier-smaller ml.* instance, and prices the saving from the real BatchTransform rate delta between the two SKUs.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1614 |
| Category | rightsizing |
| Severity | low |
| Metric | none — pure configuration read |
| Source | sagemaker_transform_rightsizing.go |
Advice for a job that no longer exists
Batch transform jobs are transient: they spin up, process, and terminate, billing per-second while they run. By the time the finding appears, the flagged job is finished and unfixable, so the recommendation is aimed at the recurring pattern, because transform jobs are rerun on schedules and from pipelines, and next month’s run can be a size smaller. The cost basis reflects that: the job’s actual measured run cost, not a 730-hour monthly projection that would inflate a two-hour job absurdly.
Reading multi-core metrics correctly
Transform-job CPU in CloudWatch is summed across vCPUs: an 8-vCPU instance scales 0–800%. The rule divides by the instance type’s published vCPU count before applying its 10% trigger, and abstains when the type’s core count cannot be resolved. The peak guard runs on the same normalized basis but deliberately skips the usual coverage minimum: a transient job can never accumulate a week of peak-band coverage, so the run-spanning recorded maximum is used directly. A possibly-understated peak can only withhold a recommendation, never invent one.
A named target priced from the billing rows AWS actually uses
“Use a smaller instance” is only actionable with a name, so the rule steps the ml.* type one rung down the size ladder (abstaining for GPU SKUs, floor sizes, and unknown families) and prices both SKUs from the SageMaker offer’s BatchTransform component rows, which are the rates this workload actually bills under (several types have no bare-rate row at all). Saving equals cost × (1 − target/current rate); missing rates or a non-cheaper target abstain rather than fall back to a flat fraction.
Inspect a job’s utilization
aws cloudwatch get-metric-statistics \ --namespace /aws/sagemaker/TransformJobs --metric-name CPUUtilization \ --dimensions Name=Host,Value=my-transform-job \ --start-time "$(date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)" \ --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ --period 3600 --statistics Average MaximumDivide by the vCPU count before judging.
Applying it to the next run
Set the smaller InstanceType in the TransformResources block of the job definition your pipeline submits, then consider whether InstanceCount or MaxConcurrentTransforms also deserves a trim. One monitored rerun on the smaller size settles the question the metrics raised.