What the scanner looks for, mapped across AWS, Azure, and Google Cloud.
Automated checks run on every scan
Categories of waste covered
Clouds — AWS, Azure & Google Cloud
This is the detection catalog — twenty-six categories of waste Cloud-Vex looks for, and what each maps to in AWS, Azure and Google Cloud. If you are trying to work out whether it would find anything in your estate, this is the page that answers it.
192 checks run on every scan — 78 on AWS, 64 on Azure, and 50 on Google Cloud. The gap between them isn’t a gap in effort: it’s each provider's own API surface, plus the categories below still marked Not yet available on the clouds that haven’t caught up yet.
Every detection is read-only. Cloud-Vex recommends an action and estimates the saving. It never executes anything.
Coverage differs by cloud — each provider exposes different APIs, and some detections need a signal one platform simply doesn’t emit. A dash (—) means the detection genuinely doesn’t apply to that platform. Not yet available means it could apply there but isn’t built yet — we’d rather say so than imply coverage we don’t have.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Unattached block storage | EBS volumes in available | Unattached managed disks | Unattached persistent disks |
| Disks attached to deleted/stopped hosts | EBS on long-stopped EC2 | Premium disks on deallocated VMs | PDs on terminated instances |
| Over-provisioned IOPS/throughput | io1/io2 provisioned IOPS far above consumed | Premium SSD v2 / Ultra Disk provisioned IOPS far above consumed | Not yet available |
| Outdated volume type | gp2 volumes eligible for gp3 | Standard HDD/SSD tier mismatch | Not yet available |
Why it matters: the single most common finding, and the easiest to act on. A detached volume does nothing and bills forever.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Snapshots older than threshold | EBS snapshots | Disk snapshots | PD snapshots |
| Snapshots of deleted source volumes | Orphaned EBS snapshots | Orphaned disk snapshots | Orphaned PD snapshots |
| Unused machine images | AMIs with no launches | Unused managed images, gallery versions | Unused custom & machine images |
| Database snapshots of deleted instances | Orphaned RDS manual snapshots | Orphaned SQL exports | — |
| No snapshot lifecycle policy | Missing DLM policy | Not yet available | Missing snapshot schedule retention |
Why it matters: snapshots accumulate silently for years. Nobody deletes them because nobody is sure what depends on them — which is exactly the dependency mapping Cloud-Vex provides.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Stopped instances retaining storage | Stopped EC2 with EBS attached | Deallocated VMs retaining disks | Terminated instances retaining PDs |
| Stopped but not deallocated | — | VMs in Stopped rather than Stopped (deallocated) — still billing full compute | — |
| Long-stopped databases | RDS stopped >7 days (auto-restarts, storage bills throughout) | SQL DB paused, storage billing | Cloud SQL stopped, storage billing |
Why it matters: the Azure Stopped vs Stopped (deallocated) distinction is one of the most expensive misunderstandings in cloud. A VM stopped from inside the guest OS keeps billing at full rate.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Idle virtual machines | Low CPU/network EC2 over window | Low-utilization VMs | Idle Compute Engine instances |
| Idle autoscaling groups | ASG at floor with no traffic | VM Scale Sets at minimum | Instance groups at minimum |
| Never-started instances | EC2 launched and never used | VMs provisioned, never accessed | Instances with no login/network |
| Dev/test running outside business hours | No schedule attached | No auto-shutdown policy | No instance schedule |
Signal: CPU, network in/out, and disk I/O across a configurable window — 14 days by default. Every finding shows the evidence and thresholds used, so an engineer can dispute it.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Oversized compute | Compute Optimizer recommendations | Azure Advisor rightsizing | Recommender machine type |
| Oversized serverless | Lambda over-allocated memory | Not yet available | Cloud Functions over-allocated memory |
| Oversized containers | ECS/Fargate task sizing | Container Apps sizing | Cloud Run instance sizing |
| Oversized databases | RDS instance class vs load | SQL DB DTU/vCore tier | Cloud SQL machine type |
Approach: ingest the native recommendation APIs rather than reinventing them. They’re free, first-party, and carry credibility with skeptical engineers. Cloud-Vex adds the layer they can’t — cross-cloud normalization and dollar-ranked prioritization across the whole estate at once.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Unassociated public IPs | Unattached Elastic IPs | Unassociated Standard-SKU public IPs | Unattached reserved static IPs |
| All public IPv4 addresses | Billed hourly since Feb 2024, attached or not | Standard SKU billed | Billed when reserved |
| Orphaned network interfaces | Detached ENIs | Unattached NICs | — |
| Unused VPC endpoints | Interface endpoints billing hourly per AZ with no traffic | Private Endpoints unused | Not yet available |
| Empty/unused subnets and route tables | Hygiene only, no direct cost | Hygiene only | Hygiene only |
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| No healthy backends | ALB/NLB/CLB with empty target groups | LB / App Gateway with empty backend pool | Forwarding rules with no backend |
| Near-zero request volume | ALB/NLB with negligible traffic | App Gateway with negligible traffic | LB with negligible traffic |
| Legacy generation | Classic Load Balancers still running | Basic SKU LBs (retiring) | — |
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Idle NAT gateways | NAT GW with near-zero data processed | NAT Gateway idle | Cloud NAT idle |
| Unused VPN | VPN connections down or no traffic | VPN Gateways idle | Cloud VPN tunnels idle |
| Unused dedicated interconnect | Direct Connect VIFs with no traffic | ExpressRoute circuits idle | Not yet available |
| Unused transit attachments | Not yet available | Not yet available | Not yet available |
Why it matters: gateways bill hourly whether or not anything flows through them. A NAT gateway left behind from a decommissioned VPC is pure loss, and nobody ever looks at it.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Zero-connection databases | RDS/Aurora with no connections over window | SQL DB with no sessions | Cloud SQL with no connections |
| Over-provisioned throughput | DynamoDB provisioned RCU/WCU vs consumed | Cosmos DB RU/s vs consumed | Not yet available |
| Idle caches | ElastiCache clusters with no hits | Azure Cache for Redis idle | Memorystore idle |
| Underused elastic pools | Aurora Serverless min capacity too high | SQL elastic pools underutilized | — |
| Unused secondary indexes | DynamoDB GSIs with no reads | Not yet available | — |
| Idle read replicas | RDS replicas with no reads | Geo-replicas unused | Cloud SQL read replicas unused |
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Idle cluster control plane | EKS cluster with no workloads (~$73/mo each) | AKS cluster idle | GKE cluster management fee, idle |
| Underutilized node pools | EKS node groups over-provisioned | AKS node pools over-provisioned | GKE node pools over-provisioned |
| Services scaled to zero but resourced | ECS services with 0 tasks | Not yet available | Cloud Run min-instances idle |
| Orphaned persistent volumes | Not yet available | Not yet available | Not yet available |
Why it matters: forgotten clusters are a classic. An EKS or GKE control plane costs roughly $73/month doing nothing at all, and teams routinely leave three or four behind after a migration.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Incomplete multipart uploads | Abandoned parts billing invisibly | — | — |
| No lifecycle policy | Buckets without lifecycle rules | Containers without lifecycle management | Buckets without lifecycle rules |
| Wrong storage class for access pattern | Standard holding cold data | Hot tier holding cold data | Standard class holding archival data |
| Accumulated non-current versions | Versioning on, no expiration rule | Blob versions/snapshots unmanaged | Non-current object versions unmanaged |
| Empty buckets | Hygiene only | Hygiene only | Hygiene only |
Why it matters: incomplete multipart uploads are the best hidden-cost finding in the catalog. They don’t appear in the console object listing, they bill indefinitely, and a busy account can hold terabytes of them.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Idle warehouses | Redshift clusters with no queries | Not yet available | Not yet available |
| Idle processing clusters | EMR clusters running with no jobs | Not yet available | Dataproc clusters idle |
| Over-provisioned streaming | Kinesis shards above throughput | Event Hubs TUs above throughput | Not yet available |
| Idle search/observability | OpenSearch domains with no queries | Not yet available | — |
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Never-expiring log retention | CloudWatch log groups set to never expire | Log Analytics over-retained | Cloud Logging buckets over-retained |
| Logs from deleted resources | Log groups with no recent writes (Lambda only) | Not yet available | Not yet available |
| Excessive custom metrics | CloudWatch custom metrics unused | Not yet available | Unused custom metrics |
Why it matters: CloudWatch defaults to infinite retention. Multiply that by every Lambda function anyone ever deployed and it becomes a real line item that nobody has ever looked at.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Unused provisioned concurrency | Lambda provisioned concurrency with no invocations | Functions Premium plan idle | Cloud Run min-instances with no traffic |
| Never-invoked functions | Lambda with zero invocations | Functions with zero executions | Cloud Functions with zero calls |
| Idle CDN | CloudFront distributions with negligible requests | Front Door / CDN profiles idle | — |
| Orphaned DNS | Route 53 zones for domains no longer resolving | Azure DNS zones orphaned | Cloud DNS zones orphaned |
| Unused API stages | API Gateway stages with no calls | Not yet available | Not yet available |
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Untagged/stale images | ECR without lifecycle policy | ACR untagged manifests | Artifact Registry stale images |
| Over-provisioned registry tier | — | ACR Premium where Standard suffices | — |
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Expiring commitments | RIs and Savings Plans expiring in <30 days | Not yet available | Resource-based CUDs expiring in <30 days |
| Underutilized commitments | RI/SP utilization below threshold | Not yet available | Not yet available |
| Coverage gaps | Steady-state usage on on-demand rates | Not yet available | Not yet available |
| Licensing benefit unused | — | Azure Hybrid Benefit not applied | — |
Boundary: Cloud-Vex reports commitment health. It does not purchase, sell, or exchange commitments — that’s a different product with different risk, and buying financial instruments on a customer’s behalf is outside the read-only model.
| Detection | Applies to |
|---|---|
| Resources in regions you don’t operate in | Not yet available — needs a per-account “expected regions” setting we haven’t built yet |
| Untagged / unowned resources | All three — no owner means no one will ever delete it |
| Resources orphaned from deleted IaC stacks | CloudFormation only today. ARM/Bicep and Terraform state drift are not yet available |
| Duplicate workloads across clouds | Not yet available — needs findings joined across a customer’s accounts, which is a different layer of the product than a single-account check |
| Cost anomalies | AWS only today, via Cost Explorer’s own anomaly detection. Azure and Google Cloud are not yet available |
| Marketplace subscriptions for dead resources | Not yet available on any cloud — none of the three publishes a buyer-side API for a customer’s own active subscriptions |
Why the region check matters: a proof-of-concept spun up in ap-southeast-2 two years ago is invisible to everyone who only ever looks at their home region. This one’s on the roadmap, not live yet — see the pending items above.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Compute plan with nothing deployed | Elastic Beanstalk environment with no application | App Service Plan with zero apps — bills the full tier regardless | Not yet available |
| Old deployment versions retaining capacity | Lambda versions with provisioned concurrency | Not yet available | Not yet available |
| Over-provisioned plan tier | Beanstalk instance type above need | App Service Plan Premium where Basic suffices | Not yet available |
| Idle Cloud Run / Container Apps revisions | — | Not yet available | Cloud Run revisions with min-instances |
Why it matters: an Azure App Service Plan bills its full tier whether or not a single app is deployed on it. Delete the app, forget the plan, pay forever. App Engine is the same story — old versions keep instances allocated after traffic has been shifted away.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Notebook instances left running | SageMaker notebook instances idle | Not yet available | Not yet available |
| Idle GPU/accelerator instances | GPU EC2 with no utilization | NC/ND/NV-series VMs idle | Any instance with an attached accelerator, idle |
| Idle inference endpoints | SageMaker endpoints with no invocations | Not yet available | Not yet available |
| Abandoned training artifacts | S3 model artifacts from dead experiments | Not yet available | Not yet available |
| Idle ML compute clusters | Not yet available (EMR clusters are covered separately, see §12) | Not yet available | Not yet available |
Why it matters: this is the highest dollar-per-resource category in the catalog. A single idle GPU instance can run $1,000–$3,000/month, and notebook environments are notorious for being started on a Friday and rediscovered in a quarterly review.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Desktops provisioned for departed users | Not yet available | Not yet available | — |
| Wrong billing mode | WorkSpaces on AlwaysOn where AutoStop fits usage | Not yet available | — |
| Idle app streaming | AppStream fleets with no sessions | — | — |
Why it matters: virtual desktops for employees who left is one of the cleanest findings there is — nobody deprovisions them, because the offboarding checklist rarely reaches the VDI console. It’s on the roadmap; today’s reliable universal APIs for resolving desktop-to-user assignment against a directory aren’t there yet on either cloud.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Backup items for deleted resources | AWS Backup recovery points for deleted sources | Recovery Services vault items for deleted VMs — keeps billing | Not yet available |
| Retention far beyond stated policy | Daily backups retained for years | Not yet available | Not yet available |
| Replication to targets nobody reads | Not yet available | Not yet available | Not yet available |
| DR standby for decommissioned workloads | Not yet available | Not yet available | Not yet available |
| Duplicate backup tooling | AWS Backup plus a third-party agent covering the same resources | Same | Not yet available |
Why it matters: Azure Recovery Services vaults continue billing for backup items after the source VM is deleted. The VM is gone from every inventory view, but the protected item persists.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| No lifecycle/tiering policy | EFS without IA lifecycle transition | Not yet available | Not yet available |
| Over-provisioned throughput/capacity | EFS provisioned throughput unused | Premium file shares over-provisioned | Filestore capacity far above used |
| Idle high-performance file systems | FSx for Lustre systems with no I/O | Not yet available | Not yet available |
| Orphaned mount targets | EFS mount targets in empty subnets | — | — |
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Traffic paying NAT charges that a free endpoint would eliminate | S3/DynamoDB traffic through NAT instead of a free gateway endpoint | Storage traffic through NAT instead of a service endpoint | Storage traffic through Cloud NAT instead of Private Google Access |
| Cross-AZ chatter between co-locatable resources | Not yet available | Not yet available | Not yet available |
| Public-path traffic between own resources | Not yet available | Not yet available | Not yet available |
| Redundant interface endpoints | Multiple interface endpoints where one suffices | Duplicate private endpoints | Duplicate PSC endpoints |
Why it matters: S3 gateway endpoints are free on AWS and eliminate NAT data-processing charges entirely for S3 traffic. An account moving heavy S3 volume through a NAT gateway is paying real money — often thousands a month — for something a one-line configuration change makes free. This is the highest-ROI single recommendation in the catalog.
Cloud-Vex does not do general data-transfer optimization. Architectural network waste — a missing free endpoint, a needless cross-AZ hop — is a different thing and is squarely in scope for the product. The missing-free-endpoint check ships today; cross-AZ and public-path traffic checks need flow logs, which are opt-in on every cloud and not yet built — see above.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Self-hosted runners idle 24/7 | EC2-based GitHub/GitLab runners with no jobs | VM-based agents idle | GCE-based runners idle |
| Idle build projects | CodeBuild projects with no builds | Not yet available | Not yet available |
| Over-provisioned parallelism | Not yet available | Not yet available | Not yet available |
| Orphaned build artifacts | S3 artifact buckets with no lifecycle | Not yet available | Artifact storage unpruned |
Why it matters: self-hosted runners are provisioned once and run continuously, but they’re only doing work during business hours on weekdays — roughly 25% of the time they’re billed for.
Individually trivial, collectively material at scale. These are reported as an aggregate line rather than one finding per item.
| Detection | AWS | Azure | Google Cloud |
|---|---|---|---|
| Unused encryption keys | KMS customer-managed keys with no usage (~$1/mo each) | Not yet available | Not yet available |
| Unused secrets | Secrets Manager secrets never retrieved (~$0.40/mo each) | Not yet available | Not yet available |
| Detailed monitoring where basic suffices | EC2 detailed monitoring (~$2.10/instance/mo) | — | — |
| Idle config/compliance recorders | Config rules evaluating dead resources | — | — |
| Orphaned parameter stores | Advanced-tier SSM parameters unused | Not yet available | — |
Why it matters: a thousand unused KMS keys is $1,000/month. Nobody notices, because no single item is worth noticing.
The most valuable category, and the one native tools handle worst — because these require watching change over time rather than inspecting current state. That’s also why this whole category is roadmap, not live: every detection below needs a baseline built from multiple scans over time, and scan-history comparison is a design we haven’t built yet, not a per-check gap. Everything else in this catalog is a point-in-time read; this table shows what we’re building toward.
| Detection | What it catches |
|---|---|
| Non-production running 24/7 | Dev, test, staging, and QA resources billed continuously for workloads used ~50 hours a week. Typically 65–70% waste on those resources |
| Temporary changes never reverted | Scaling floors raised during an incident, instance tiers upgraded “just for the migration”, provisioned concurrency added for a launch — and never rolled back |
| Free-tier graduation | Resources that started billing when a 12-month trial expired, with nobody watching for the transition |
| Dormant accounts, subscriptions, and projects | Whole scopes with small but nonzero spend and no human activity in months |
| Post-migration leftovers | DMS replication instances, DataSync tasks, and Site Recovery still running after cutover completed |
| Burstable surplus credits | T-family instances in unlimited mode accruing surplus credit charges — cheaper on a larger fixed size |
| Growth without corresponding usage | Storage or instance count climbing while requests stay flat |
| Orphaned by team departure | Resources whose only tagged owner no longer exists in the directory |
Why it matters: “we upgraded that during the outage in March and nobody changed it back” is the most common origin story for large cloud waste, and no per-resource inspection will ever catch it. It requires baseline and drift — which is where scanning continuously will earn its keep over a one-time audit, once this category ships.
Every finding carries a dollar figure computed on effective amortized cost — after EDP, Enterprise Agreement, Savings Plan, Reserved Instance, and CUD discounts. Never list price.
Where the effective rate can’t be resolved, the finding is flagged
confidence: medium and says so on the face of it.
Each finding also distinguishes:
The permission model shows exactly what is granted in each cloud, and the scan cycle shows every API a scan touches.
Looking for something not on this list? Email support@cloud-vex.com.
Join the waitlist