AWS
VPC
troubleshooting
cloud computing
network management

I can't delete my VPC

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When AWS refuses to delete a VPC, the problem is almost always a dependency. A VPC cannot be removed while resources are still attached to it, and AWS returns errors such as DependencyViolation until those dependencies are gone. The fastest way to solve it is to treat deletion as a dependency cleanup exercise rather than repeatedly pressing Delete in the console.

Why VPC Deletion Fails

A VPC is the parent object for many networking resources. Even if you already terminated EC2 instances, other objects may still hold references to the VPC.

Common blockers include:

  • subnets
  • internet gateways
  • NAT gateways
  • elastic network interfaces
  • route tables with associations
  • VPC endpoints
  • security groups referenced by other resources
  • VPC peering or transit gateway attachments

The AWS console may show only one blocker at a time, so the CLI is often faster for a full inspection.

Start with the Error Message

If you try deletion through the CLI, AWS usually gives a clearer error:

bash
aws ec2 delete-vpc --vpc-id vpc-0123456789abcdef0

If the VPC still has dependencies, you will usually get a DependencyViolation response. That does not tell you every dependency, but it confirms the diagnosis.

A Practical Cleanup Checklist

The most reliable workflow is to enumerate the remaining resources inside the VPC and delete them in dependency order.

bash
1VPC_ID=vpc-0123456789abcdef0
2
3aws ec2 describe-subnets --filters Name=vpc-id,Values=$VPC_ID
4aws ec2 describe-network-interfaces --filters Name=vpc-id,Values=$VPC_ID
5aws ec2 describe-nat-gateways --filter Name=vpc-id,Values=$VPC_ID
6aws ec2 describe-vpc-endpoints --filters Name=vpc-id,Values=$VPC_ID
7aws ec2 describe-route-tables --filters Name=vpc-id,Values=$VPC_ID
8aws ec2 describe-internet-gateways --filters Name=attachment.vpc-id,Values=$VPC_ID

That list catches the most common blockers quickly.

A typical deletion order is:

  1. terminate instances and load balancers using the VPC
  2. delete NAT gateways and wait for them to finish deleting
  3. delete VPC endpoints
  4. detach and delete the internet gateway
  5. delete non-main route tables or remove associations
  6. delete subnets
  7. delete any remaining custom security groups or interfaces
  8. delete the VPC

Waiting matters. Some AWS resources, especially NAT gateways and interfaces created by managed services, do not disappear instantly.

Internet Gateway and Subnet Example

A very common case is a VPC that still has an attached internet gateway and one or more subnets.

bash
1aws ec2 detach-internet-gateway \
2  --internet-gateway-id igw-0123456789abcdef0 \
3  --vpc-id vpc-0123456789abcdef0
4
5aws ec2 delete-internet-gateway \
6  --internet-gateway-id igw-0123456789abcdef0
7
8aws ec2 delete-subnet --subnet-id subnet-0123456789abcdef0
9aws ec2 delete-subnet --subnet-id subnet-0fedcba9876543210

Only after the subnets are gone can the VPC be deleted.

Managed Services Often Leave Hidden Interfaces

One of the most confusing blockers is the elastic network interface created by another AWS service. Lambda in a VPC, RDS, EKS, PrivateLink endpoints, and load balancers can all leave ENIs behind. If describe-network-interfaces returns an interface owned by another service, delete the parent service resource first rather than trying to force-delete the ENI.

That is why looking only at EC2 instances is not enough. The VPC may be empty from an EC2 point of view while still being used by another managed service.

Infrastructure as Code Can Make This Easier

If the VPC was created by CloudFormation, CDK, or Terraform, it is often better to destroy the stack from the same tool. Manual deletion from the console can leave resources out of sync with the infrastructure definition.

For example, if Terraform created the VPC, terraform destroy can remove dependencies in the right order as long as the state is accurate.

Common Pitfalls

The biggest mistake is trying to delete the VPC before deleting subnets. Subnets are one of the most fundamental blockers and must go before the VPC can disappear.

Another mistake is forgetting about managed-service ENIs. These often make the VPC look empty while AWS still sees active attachments.

A third issue is not waiting for asynchronous deletions to finish. NAT gateways and similar resources can remain in a deleting state for several minutes.

Summary

  • A VPC usually fails to delete because some dependent resource still exists
  • Start by checking for subnets, gateways, ENIs, NAT gateways, endpoints, and route tables
  • 'DependencyViolation means the diagnosis is correct even if the error is not specific enough'
  • Delete dependencies in order, and wait for asynchronous resources to finish deleting
  • If the VPC came from CloudFormation or Terraform, destroying it from the same tool is often the cleanest fix

Course illustration
Course illustration

All Rights Reserved.