Reduce Azure Container Instances costs through right-sizing resource requests, lifecycle automation, platform selection analysis, and commitment discounts for steady-state workloads.

Here is a scenario that plays out in Azure subscriptions more often than anyone admits: a developer spins up a container group for a quick data processing job, requests 2 vCPUs and 4 GB of memory because the defaults seemed reasonable, and moves on. Three months later, that container is still running 24/7, averaging 0.3 vCPUs, and silently billing for the full 2. Multiply that by 20 client tenants and you have a line item nobody budgeted for.
Most ACI cost problems come down to one misunderstanding: ACI bills per second for every vCPU and GB of memory you request, not what you use. The most effective ACI cost reductions come from aligning resource requests to actual consumption, automating stop/start lifecycles for idle containers, choosing the right platform for your workload pattern, and applying commitment discounts for steady-state workloads.
Key Takeaways at a Glance:
ACI occupies a specific niche: serverless containers with per-second billing and no cluster management. That simplicity creates a false sense of cheapness. The per-second model means you only pay for what you run -- but you pay for what you request, not what you consume. This disconnect is the root of most ACI cost traps.
Common ACI cost traps:
Understanding the billing model is the foundation of every optimization. ACI charges three components, all billed per second with a minimum of 60 seconds.
| Component | Rate (Linux, East US) | Notes |
|---|---|---|
| vCPU | $0.0000112/second ($0.0405/hour) | Rounded up to whole vCPUs |
| Memory (GB) | $0.00000123/GB-second ($0.00445/GB-hour) | Rounded up to 0.1 GB |
| Windows Software | $0.0000120/vCPU-second ($0.0432/vCPU-hour) | Add-on for Windows OS containers |
Monthly cost examples (730 hours, Linux, East US):
ACI Monthly Cost Examples (Linux, East US, 730 hours)
=====================================================
1 vCPU / 1 GB:
vCPU: 1 x $0.0405/hr x 730 hr = $29.57
Memory: 1 x $0.00445/hr x 730 hr = $3.25
Total: $32.82/month
2 vCPU / 4 GB:
vCPU: 2 x $0.0405/hr x 730 hr = $59.13
Memory: 4 x $0.00445/hr x 730 hr = $12.99
Total: $72.12/month
4 vCPU / 16 GB:
vCPU: 4 x $0.0405/hr x 730 hr = $118.26
Memory: 16 x $0.00445/hr x 730 hr = $51.98
Total: $170.24/monthTwo key billing details most people miss:
1. Windows surcharge nearly doubles the bill. Adding the Windows software fee to a 2 vCPU container adds $0.0432/hr per vCPU = $63.07/month. That turns a $72.12 Linux container into a $135.19 Windows container -- a 96% increase for the same workload.
2. Rounding applies to requests, not usage. If you request 1.5 vCPUs, you are billed for 2. If you request 3.7 GB of memory, you are billed for 3.7 GB (rounded to nearest 0.1 GB). The vCPU rounding to whole numbers is the one that catches people.
Use this decision tree to prioritize which optimizations to tackle first for each container group:
ACI Cost Optimization Priority Flowchart
=========================================
[Start] Is the container group running Windows?
|
+-- YES --> Can it run on Linux?
| |
| +-- YES --> MIGRATE TO LINUX (saves ~49% immediately)
| +-- NO --> Continue to next check
|
+-- NO --> Continue to next check
|
+-- Is the container running 24/7?
|
+-- YES --> Does it need to run 24/7?
| |
| +-- NO --> AUTOMATE STOP/START (saves 50-67%)
| +-- YES --> Is it a steady-state workload?
| |
| +-- YES --> APPLY SAVINGS PLAN (saves 27-52%)
| +-- NO --> Continue to next check
|
+-- NO --> Continue to next check
|
+-- Are resource requests aligned to actual usage?
|
+-- NO --> RIGHT-SIZE REQUESTS (saves 30-70%)
+-- YES --> Is this workload better suited for another platform?
|
+-- AKS (high density) --> MIGRATE
+-- Container Apps (event-driven) --> EVALUATE
+-- App Service (web apps) --> EVALUATE
+-- KEEP ON ACI (ephemeral/serverless fit)Right-sizing is the highest-impact optimization because ACI bills for requested resources, not consumed resources. A container requesting 2 vCPUs but averaging 0.3 vCPUs is wasting 85% of its compute spend.
5-step right-sizing process:
CLI commands for right-sizing analysis:
# List all container groups with their resource requests
az container list --query "[].{Name:name, ResourceGroup:resourceGroup, \
Containers:containers[].{Name:name, CPU:resources.requests.cpu, \
MemoryGB:resources.requests.memoryInGb}, \
OsType:osType, State:instanceView.state}" -o table
# Get CPU utilization metrics for a container group (last 7 days)
az monitor metrics list \
--resource /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.ContainerInstance/containerGroups/<name> \
--metric CpuUsage \
--interval PT1H \
--start-time $(date -d '7 days ago' -u +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--aggregation Average Maximum \
--query "value[0].timeseries[0].data[].{Time:timeStamp, AvgCPU:average, MaxCPU:maximum}" -o table
# Get memory utilization metrics
az monitor metrics list \
--resource /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.ContainerInstance/containerGroups/<name> \
--metric MemoryUsage \
--interval PT1H \
--start-time $(date -d '7 days ago' -u +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--aggregation Average Maximum \
--query "value[0].timeseries[0].data[].{Time:timeStamp, AvgMemMB:average, MaxMemMB:maximum}" -o table
# Redeploy with right-sized resources (requires delete + create)
az container delete --name <name> --resource-group <rg> --yes
az container create \
--name <name> \
--resource-group <rg> \
--image <image> \
--cpu 1 \
--memory 1.5 \
--os-type LinuxFailure mode warning: ACI does not support in-place resource updates. You must delete and recreate the container group, which means downtime. For production workloads, use a blue-green deployment pattern: create the new container group first, validate it, then delete the old one. If the container uses a public IP, the IP will change unless you use an Application Gateway or Azure Front Door in front of it.
The Windows software surcharge adds $0.0432/vCPU-hour on top of the base compute cost. For a 2 vCPU container running 24/7, that is $63.07/month in additional charges -- nearly doubling the bill. If your application can run on Linux (most .NET 6+ apps can), switching the OS type is the single highest-impact change per container.
| Configuration | Linux Cost/mo | Windows Cost/mo | Difference |
|---|---|---|---|
| 1 vCPU / 1.5 GB | $36.23 | $67.77 | +$31.54 (+87%) |
| 2 vCPU / 4 GB | $72.12 | $135.19 | +$63.07 (+87%) |
| 4 vCPU / 16 GB | $170.24 | $296.38 | +$126.14 (+74%) |
Note: Windows containers on ACI also have limited region availability and do not support GPU SKUs. If you are running .NET Framework 4.x applications that cannot be ported to .NET 6+, Windows containers are required. For everything else, Linux is the cost-optimal choice.
ACI is not always the cheapest option. The right platform depends on your workload pattern: how long it runs, how predictable the load is, and how many containers you manage.
Platform cost comparison (1 vCPU / 2 GB, Linux, East US, 730 hours/month):
| Platform | Monthly Cost | Billing Model | Best For |
|---|---|---|---|
| ACI | $38.47 | Per-second (requested) | Ephemeral, batch, always-on (small count) |
| Container Apps (Consumption) | $43.80 | Per-second (active) + requests | Event-driven, scale-to-zero |
| AKS (D2s v3 node) | $70.08 | Per-node (VM pricing) | High-density, many containers per node |
| App Service (B1) | $13.14 | Fixed plan | Web apps, always-on |
Important insight: ACI is actually cheaper than Container Apps for 24/7 always-on workloads. Container Apps adds a per-request charge and has higher per-second rates. If your container runs continuously and does not need scale-to-zero, ACI is the better deal. Container Apps wins when you need event-driven auto-scaling or scale-to-zero during idle periods.
One of the most common cost wins we see: organizations running scheduled WebJobs on a B1 App Service plan ($13.14/month) for a task that runs 5 minutes per day. Moving that to ACI reduces the cost to the seconds the job actually runs.
WebJob to ACI Migration Cost Comparison
========================================
B1 App Service Plan (always-on for WebJob):
Cost: $13.14/month (24/7, regardless of job runtime)
ACI (1 vCPU / 1 GB, 5 min/day, 30 days):
vCPU: 1 x $0.0000112/sec x 300 sec x 30 days = $0.10
Memory: 1 x $0.00000123/sec x 300 sec x 30 days = $0.01
Total: $0.11/month
Savings: $13.03/month (99.2% reduction)
Annual: $156.36/year per job
With 10 scheduled jobs across 5 tenants:
Before: $657/month (10 x B1 plans, some shared)
After: $5.50/month (50 ACI jobs)
Savings: $651.50/month = $7,818/yearImplementation -- schedule ACI with Logic Apps:
# Create a container group with restart policy "Never" (run once)
az container create \
--name batch-job-daily \
--resource-group rg-batch \
--image myregistry.azurecr.io/batch-processor:latest \
--cpu 1 \
--memory 1 \
--os-type Linux \
--restart-policy Never \
--environment-variables JOB_TYPE=daily
# Use Azure Logic Apps or Automation to trigger on schedule:
# 1. Logic App recurrence trigger (e.g., daily at 02:00 UTC)
# 2. Action: "Create or update a container group"
# 3. Action: Wait for container to complete (poll state)
# 4. Action: Delete container group (stop billing)
# Or use az container start for pre-created groups:
az container start --name batch-job-daily --resource-group rg-batch
# ... job runs ...
az container stop --name batch-job-daily --resource-group rg-batchAKS virtual nodes (powered by ACI) let you burst Kubernetes pods to ACI without provisioning additional VM nodes. Instead of scaling up your AKS node pool for intermittent spikes, you pay per-second for the burst pods only.
Limitations of AKS virtual nodes:
# Enable virtual nodes on an existing AKS cluster
az aks enable-addons \
--resource-group rg-aks \
--name my-cluster \
--addons virtual-node \
--subnet-name aci-subnet
# Deploy a pod that tolerates the virtual node taint
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: burst-processor
spec:
containers:
- name: processor
image: myregistry.azurecr.io/processor:latest
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "2"
memory: "4Gi"
tolerations:
- key: virtual-kubelet.io/provider
operator: Exists
- key: azure.com/aci
effect: NoSchedule
nodeSelector:
kubernetes.io/role: agent
beta.kubernetes.io/os: linux
type: virtual-kubelet
EOF
# Scale a deployment to virtual nodes during burst
kubectl scale deployment burst-processor --replicas=10
# Pods exceeding node capacity will schedule on virtual nodes (ACI)
# Cost: per-second billing only for the burst durationSince ACI bills per second, every second a container runs idle is wasted spend. Lifecycle automation is the second-highest impact optimization after right-sizing.
Many ACI container groups run during business hours but sit idle overnight and on weekends. Automating stop/start can eliminate 50-67% of the bill depending on the schedule.
PowerShell Automation Runbook:
# Azure Automation Runbook: ACI Lifecycle Management
# Schedule: Run every hour, evaluates current time against schedule
param(
[string]$ResourceGroupName,
[string]$TagName = "aci-schedule",
# Tag value format: "start=08:00,stop=18:00,tz=Eastern Standard Time,days=Mon-Fri"
[bool]$DryRun = $true
)
Connect-AzAccount -Identity
# Get all container groups with the schedule tag
$containerGroups = Get-AzContainerGroup -ResourceGroupName $ResourceGroupName |
Where-Object { $_.Tag.ContainsKey($TagName) }
foreach ($cg in $containerGroups) {
$schedule = $cg.Tag[$TagName]
$parts = @{}
$schedule -split ',' | ForEach-Object {
$kv = $_ -split '='
$parts[$kv[0]] = $kv[1]
}
$tz = [System.TimeZoneInfo]::FindSystemTimeZoneById($parts['tz'])
$localTime = [System.TimeZoneInfo]::ConvertTimeFromUtc((Get-Date).ToUniversalTime(), $tz)
$currentHour = $localTime.ToString("HH:mm")
$currentDay = $localTime.DayOfWeek.ToString().Substring(0,3)
$activeDays = $parts['days'] -split '-'
$isActiveDay = $activeDays -contains $currentDay -or
($activeDays.Count -eq 2 -and
[array]::IndexOf(@('Mon','Tue','Wed','Thu','Fri','Sat','Sun'), $currentDay) -ge
[array]::IndexOf(@('Mon','Tue','Wed','Thu','Fri','Sat','Sun'), $activeDays[0]) -and
[array]::IndexOf(@('Mon','Tue','Wed','Thu','Fri','Sat','Sun'), $currentDay) -le
[array]::IndexOf(@('Mon','Tue','Wed','Thu','Fri','Sat','Sun'), $activeDays[1]))
$shouldRun = $isActiveDay -and ($currentHour -ge $parts['start']) -and ($currentHour -lt $parts['stop'])
$currentState = $cg.ProvisioningState
if ($shouldRun -and $currentState -ne "Running") {
if ($DryRun) {
Write-Output "[DRY RUN] Would START: $($cg.Name) (schedule: $schedule)"
} else {
Start-AzContainerGroup -Name $cg.Name -ResourceGroupName $ResourceGroupName
Write-Output "Started: $($cg.Name)"
}
} elseif (-not $shouldRun -and $currentState -eq "Running") {
if ($DryRun) {
Write-Output "[DRY RUN] Would STOP: $($cg.Name) (schedule: $schedule)"
} else {
Stop-AzContainerGroup -Name $cg.Name -ResourceGroupName $ResourceGroupName
Write-Output "Stopped: $($cg.Name)"
}
}
}Savings examples:
Lifecycle Automation Savings Examples
=====================================
Scenario 1: Business hours only (Mon-Fri, 8am-6pm)
Running hours: 10 hrs/day x 22 days = 220 hrs/month
vs. 24/7: 730 hrs/month
Reduction: 70% of hours eliminated
2 vCPU/4 GB Linux: $72.12 -> $21.74/month (savings: $50.38/month, 70%)
Scenario 2: Extended hours (Mon-Fri, 6am-10pm)
Running hours: 16 hrs/day x 22 days = 352 hrs/month
vs. 24/7: 730 hrs/month
Reduction: 52% of hours eliminated
2 vCPU/4 GB Linux: $72.12 -> $34.74/month (savings: $37.38/month, 52%)
Scenario 3: Weekdays only, 24 hours
Running hours: 24 hrs/day x 22 days = 528 hrs/month
vs. 24/7: 730 hrs/month
Reduction: 28% of hours eliminated
2 vCPU/4 GB Linux: $72.12 -> $52.13/month (savings: $19.99/month, 28%)Spot container groups run on surplus Azure capacity at up to 70% discount. They can be evicted at any time when Azure needs the capacity back, making them suitable for fault-tolerant, interruptible workloads.
Spot ACI availability (as of early 2026): Spot container groups are in preview and available in limited regions (West US, West Europe, and Southeast Asia). Check the Azure documentation for current region availability. Spot containers can be evicted with 30 seconds notice and should only be used for workloads that can handle interruption gracefully.
| Component | Standard Rate | Spot Rate | Discount |
|---|---|---|---|
| vCPU (Linux) | $0.0405/hour | ~$0.0122/hour | ~70% |
| Memory (Linux) | $0.00445/GB-hour | ~$0.00134/GB-hour | ~70% |
# Create a Spot container group (preview)
az container create \
--name batch-spot-job \
--resource-group rg-batch \
--image myregistry.azurecr.io/batch-processor:latest \
--cpu 2 \
--memory 4 \
--os-type Linux \
--priority Spot \
--restart-policy Never \
--location westus
# Spot container groups are billed at Spot rates
# They can be evicted when Azure needs the capacity
# Implement checkpointing in your application to handle eviction:
# 1. Listen for SIGTERM (30 second warning)
# 2. Save progress to Azure Storage
# 3. Resume from checkpoint on next runFor container groups that run steadily month after month, Azure Savings Plans provide significant discounts over pay-as-you-go rates. The ACI compute charges are eligible for compute savings plans.
Savings plan discount tiers:
Decision framework for savings plans:
Savings Plan Decision Framework
================================
Should you commit?
1. Is the workload expected to run for 12+ months?
+-- NO --> Stay on pay-as-you-go
+-- YES --> Continue
2. Is the monthly spend consistent (within 20% variance)?
+-- NO --> Commit to the BASE (minimum) monthly spend only
+-- YES --> Continue
3. Can you commit to 3 years?
+-- YES --> 3-year plan (~52% discount)
+-- NO --> 1-year plan (~27% discount)
Example:
2 vCPU / 4 GB Linux, 24/7 = $72.12/month pay-as-you-go
1-year savings plan: ~$52.65/month (save $19.47/month)
3-year savings plan: ~$34.62/month (save $37.50/month)CLI commands for savings plan analysis:
# View current ACI spend to determine commitment amount
az consumption usage list \
--start-date $(date -d '30 days ago' +%Y-%m-%d) \
--end-date $(date +%Y-%m-%d) \
--query "[?contains(instanceName, 'containerGroups')].{Name:instanceName, \
Cost:pretaxCost, Quantity:quantity, Unit:unitOfMeasure}" -o table
# List existing savings plans
az billing savings-plan list \
--query "[].{Name:name, Term:term, Commitment:commitment.amount, \
Utilization:utilization.aggregates[0].value}" -o table
# Purchase a savings plan (use Azure Portal for guided experience)
# Navigate to: Azure Portal > Cost Management > Savings Plans > Add
# Select: Compute Savings Plan
# Scope: Subscription or Resource Group
# Term: 1 year or 3 years
# Hourly commitment: Based on your steady-state ACI compute spendPattern: A batch processing container is created with 4 vCPUs and 16 GB because the developer was not sure how much the job would need. The actual job uses 0.8 vCPUs and 2.1 GB at peak. The container runs for 2 hours daily.
Cost impact: The oversized request costs $0.47 per run. Right-sized to 1 vCPU / 3 GB, it would cost $0.10 per run. That is $11.10/month in waste for a single job. Across 20 batch jobs, it is $222/month or $2,664/year.
Fix: Collect metrics for 7 days, identify P95 usage, right-size to 1 vCPU / 3 GB with 20% buffer.
Pattern: A container group was created for a demo or development task. Nobody stopped it. It has been running 24/7 for months with zero traffic or utilization.
Cost impact: A 2 vCPU / 4 GB Linux container running idle costs $72.12/month. Across 5 forgotten containers, that is $360.60/month or $4,327/year for zero value.
Fix: Implement mandatory tagging with expiry dates. Run a weekly automation that stops or deletes container groups past their expiry. Tag all ACI resources with owner, purpose, and expiry date.
Pattern: A .NET application is running as a Windows container on ACI because the original codebase targeted .NET Framework. The application has since been upgraded to .NET 8 but nobody changed the container base image.
Cost impact: A 2 vCPU / 4 GB Windows container costs $135.19/month versus $72.12 on Linux -- an extra $63.07/month for the same workload. Over a year, that is $756.84 per container.
Fix: Audit all Windows ACI containers. For any running .NET 6+ or .NET 8, switch the base image to the Linux variant. Test thoroughly before production migration.
Pattern: A scheduled WebJob runs on a B1 App Service plan for 5 minutes daily. The App Service plan runs 24/7 to host the WebJob, even though the job only needs 2.5 hours of compute per month.
Cost impact: B1 plan costs $13.14/month for 730 hours. The equivalent ACI job costs $0.11/month for 2.5 hours. That is $13.03/month of waste per job.
Fix: Containerize the WebJob, deploy to ACI with restart-policy Never, trigger with Logic Apps or Azure Automation on a schedule.
Pattern: An organization runs 10 ACI container groups 24/7 for a production API backend. The workload has been stable for 18 months. All containers are on pay-as-you-go pricing.
Cost impact: 10 containers at 2 vCPU / 4 GB = $721.20/month pay-as-you-go. A 1-year savings plan would cost ~$526.48/month (27% savings). A 3-year plan would cost ~$346.18/month (52% savings). That is $2,337 to $4,500/year left on the table.
Fix: Analyze the past 12 months of ACI spend. Identify the steady-state baseline. Purchase a savings plan for the baseline amount. Let pay-as-you-go cover any burst above the baseline.
ACI's per-second billing is an advantage for short-running workloads, but there is a crossover point where the per-second model becomes more expensive than a fixed-price alternative. Understanding this crossover helps you make platform decisions.
| Daily Runtime | Monthly Hours | ACI Cost (1 vCPU/2 GB) | B1 App Service | Cheaper Option |
|---|---|---|---|---|
| 5 min | 2.5 hrs | $0.11 | $13.14 | ACI |
| 1 hour | 30 hrs | $1.35 | $13.14 | ACI |
| 4 hours | 120 hrs | $5.40 | $13.14 | ACI |
| 8 hours | 240 hrs | $10.80 | $13.14 | ACI |
| 10 hours | 300 hrs | $13.50 | $13.14 | App Service |
| 18 hours | 540 hrs | $24.30 | $13.14 | App Service |
| 24 hours | 730 hrs | $38.47 | $13.14 | App Service |
Key insight: For a 1 vCPU / 2 GB workload, ACI is the cheapest option when the container runs less than ~10 hours per day (~300 hours/month). Beyond that, a B1 App Service plan at $13.14/month flat is cheaper. However, ACI remains valuable for containers that need more than 1 vCPU or more than 1.75 GB memory (which exceeds B1 limits), or when you need fast startup and no cluster management. The crossover point shifts based on container size and the alternative platform you are comparing against.
| Recommendation | Typical Savings | Complexity | Risk |
|---|---|---|---|
| Right-size resource requests | 30-70% | Medium | Low (with monitoring) |
| Switch Windows to Linux | ~49% per container | Medium | Medium (app compatibility) |
| Automate stop/start lifecycle | 50-67% | Low | Low |
| Migrate WebJobs to ACI | 90-99% | Medium | Low |
| Use Spot container groups | ~70% | Medium | High (eviction risk) |
| Apply savings plan (1-year) | ~27% | Low | Low (financial commitment) |
| Apply savings plan (3-year) | ~52% | Low | Medium (long commitment) |
| Delete abandoned containers | 100% (per container) | Low | Low (verify first) |
| AKS virtual node bursting | 40-60% | High | Medium |
No. When you stop a container group with az container stop, billing stops. The container group resource remains in Azure (so you do not lose the configuration), but you pay nothing until you start it again. This is why lifecycle automation is so effective -- you only pay for the seconds the container is running.
ACI allocates dedicated CPU cores to your container group. You can request fractional vCPUs (e.g., 0.5), but the billing rounds up to the next whole number. If you request 1.1 vCPUs, you are billed for 2. This means you should always request exactly 1, 2, or 4 vCPUs to avoid paying for unused rounding. The one exception is if you request less than 1 vCPU (e.g., 0.5), which is billed as 1 vCPU.
For always-on workloads, yes. ACI has lower per-second rates than Container Apps consumption plan. Container Apps is cheaper when you need scale-to-zero (ACI cannot scale to zero -- you either run or stop), event-driven auto-scaling, or built-in traffic splitting. For a single container running 24/7, ACI typically costs 10-15% less than Container Apps consumption tier.
No. ACI does not support in-place resource updates. You must delete the container group and recreate it with the new resource requests. For zero-downtime resizing, use a blue-green deployment: create a new container group with the desired size, route traffic to it (via Application Gateway, Azure Front Door, or DNS), then delete the old group.
ACI bills per second with a minimum of 60 seconds. If your container runs for 10 seconds, you are billed for 60 seconds. After the first 60 seconds, billing is truly per-second. This minimum is per container group creation -- if you stop and restart, the 60-second minimum applies again.
Query Azure Resource Graph for container groups in "Running" state with zero or near-zero CPU utilization over the past 7 days. Cross-reference with owner tags and expiry dates. Container groups without tags are the most common source of abandoned containers. Spotto automates this detection and flags containers with sustained low utilization.
No. Savings plans apply to standard (on-demand) ACI compute charges only. Spot containers are already discounted at ~70% and are not eligible for additional savings plan discounts. Use savings plans for your steady-state standard containers and Spot for interruptible batch workloads.
Yes. ACI supports pulling images from Azure Container Registry (ACR), Docker Hub, and other private registries. When using ACR, enable the admin user or use a managed identity for authentication. Note that image pull time counts toward your billing (the container is "running" during pull), so use smaller images and layer caching where possible to reduce startup costs.
Azure sends a SIGTERM signal 30 seconds before eviction. Your application should listen for this signal, save any in-progress work to durable storage (Azure Blob, Azure Queue), and exit gracefully. The container group is stopped after eviction. You can configure your automation to recreate Spot container groups after eviction, implementing a retry-with-checkpoint pattern.
Spotto continuously monitors your ACI container groups across all subscriptions, detecting oversized resource requests, abandoned containers running with zero utilization, Windows containers that could run on Linux, missing lifecycle automation, and savings plan opportunities. Rather than running one-off audits with CLI commands, Spotto provides ongoing visibility and actionable recommendations that keep your ACI costs aligned with actual workload requirements.
Before
$4,200/mo
15 tenants, ~20 container groups each, oversized at 2 vCPU/4 GB, many running 24/7
After
$630/mo
Right-sized to 1 vCPU/1.5 GB, lifecycle automation, batch jobs run on schedule only
Actions taken: Right-sized all container groups based on 30-day P95 metrics. Implemented stop/start automation for dev/test containers. Converted always-on batch containers to scheduled runs with restart-policy Never. Deleted 12 abandoned container groups across tenants.
Before
$526/mo
40 scheduled WebJobs across 8 B1/S1 App Service plans running 24/7
After
$32/mo
40 ACI container groups triggered by Logic Apps, running only during execution
Actions taken: Containerized all 40 WebJobs. Deployed to ACI with restart-policy Never. Created Logic App triggers for each schedule. Decommissioned 8 App Service plans. Total runtime per job: 3-15 minutes per execution.
Before
$1,800/mo
10 always-on ACI containers (4 vCPU/8 GB) processing events, idle 60% of the time
After
$660/mo
Right-sized to 2 vCPU/4 GB, lifecycle automation stops idle containers, 3-year savings plan on steady base
Actions taken: Right-sized from 4 vCPU/8 GB to 2 vCPU/4 GB based on P95 metrics. Implemented event-driven start/stop using Azure Event Grid. Applied 3-year savings plan for the 4 containers that run 24/7. Remaining 6 containers run on-demand only.
Before
$2,400/mo
35 container groups in dev/test, 20 abandoned, no tagging or lifecycle policy
After
$360/mo
20 abandoned deleted, 15 active with business-hours scheduling and right-sizing
Actions taken: Audited all dev/test container groups. Deleted 20 containers with zero utilization and no owner tags. Right-sized remaining 15 containers. Implemented mandatory tagging with expiry dates. Deployed business-hours lifecycle automation (Mon-Fri, 8am-6pm).
Before
$3,500/mo
5 dedicated D4s v3 nodes for batch processing, utilized 30% on average
After
$1,400/mo
2 steady-state nodes + virtual node bursting to ACI for batch spikes
Actions taken: Reduced AKS node pool from 5 to 2 nodes for steady-state workloads. Enabled virtual nodes (ACI) for batch workload bursting. Configured pod tolerations to schedule batch jobs on virtual nodes. Batch pods run on ACI per-second billing only during processing.
az container list across all subscriptions to catalog every container group with its resource requests, OS type, state, and tags. Export to a spreadsheet for analysis.Every optimization should have a clear rollback path:
az container list across all subscriptions to catalog every container group with its resource requests, OS type, state, and tags. Identify abandoned containers immediately.The challenges outlined in this article — oversized container requests, missing lifecycle automation, Windows container surcharges, abandoned dev/test containers — are the same ones our customers work through across their Azure environments. The difference is they use Spotto to surface these opportunities automatically, rather than running the analysis by hand.
Spotto continuously analyzes your Azure Container Instances to detect oversized resource requests, abandoned containers, missing lifecycle automation, and platform mismatches — giving you clear, actionable recommendations to eliminate container waste across every subscription.
Free TrialDisclaimer: This article is provided for informational purposes only and does not constitute professional advice. Azure pricing, features, and service behaviour may have changed since publication. Always validate recommendations against your specific environment and consult Microsoft's official documentation before making changes to production infrastructure. Spotto is not liable for any actions taken based on the content of this article.