Ran into a weird problem, when an AWS EC2 instance was replaced on every Terraform run.
The EC2 instance is built using Terraform. The "aws_instance" module from Hashicorp is used in this situation and looks pretty straightforward and not too complicated:
resource "aws_instance" "onl-varnish01-t" {
ami = "ami-02003f9f0fde924ea"
instance_type = "t3.micro"
subnet_id = "subnet-xxxxxxxxxxxxxxxxxx"
security_groups = [aws_security_group.varnish_ec2_sg.id]
key_name = aws_key_pair.ck2025.key_name
tags = {
Name = "onl-varnish01-t"
Role = "varnish"
}
}
But on every terraform plan I saw that the instance(s) would be destroyed and re-created from scratch.
Note: This is using the HCP Platform (formerly known as Terraform Cloud).
A deeper look into the planned changes showed multiple changes of the EC2 instance (although there was no change in the code). One change caught my eye:
The security_groups change had an additional description: Forces replacement.
After an excellent hint from Thomas Weiss, a Terraform expert I'm in contact with for this project, it turned out to be a problem with security_groups used in the resource. The documentation states:
If you are creating Instances in a VPC, use vpc_security_group_ids instead.
Well, that's the case here. I have an existing VPC and I want to create instances using the existing VPC.
According to this information, I replaced security_groups with vpc_security_group_ids:
resource "aws_instance" "onl-varnish01-t" {
ami = "ami-02003f9f0fde924ea"
instance_type = "t3.micro"
subnet_id = "subnet-xxxxxxxxxxxxxxxxxx"
vpc_security_group_ids = [aws_security_group.varnish_ec2_sg.id]
key_name = aws_key_pair.ck2025.key_name
tags = {
Name = "onl-varnish01-t"
Role = "varnish"
}
}
After another terraform plan this seemed to work as it should: No changes detected (as the EC2 instances were already created in a previous run):
Now the question arises, why did I use security_groups instead of vpc_security_group_ids in the aws_instance resource?
As Terraform is rather new for me (I've known what it is for a long time, but never actually got to work with it), I used Grok AI to help me create a TF file with the relevant AWS resources. And Grok's example contained the aws_instance resource - with the security_groups option. Grok also seemed unaware that this situation might cause a replacement of the existing EC2 instance(s). When I added this hint, Grok explained this with changes in the code - which didn't happen.
This whole situation is a pretty good real life example on AI usage: Good ideas and very helpful input (especially for previously unknown topic to the human), but always verify with an expert in that field.
Mike Anderson from Florida wrote on Sep 3rd, 2025:
Spot-on article! I’ve been bitten by that exact Terraform behavior before—security_groups silently locks you into replacement cycles in a VPC. This post saved me from repeating it elsewhere. And the AI caveat is a nice, timely reminder for us all.
AWS Android Ansible Apache Apple Atlassian BSD Backup Bash Bluecoat CMS Chef Cloud Coding Consul Containers CouchDB DB DNS Databases Docker ELK Elasticsearch Filebeat FreeBSD Galera Git GlusterFS Grafana Graphics HAProxy HTML Hacks Hardware Icinga Influx Internet Java KVM Kibana Kodi Kubernetes LVM LXC Linux Logstash Mac Macintosh Mail MariaDB Minio MongoDB Monitoring Multimedia MySQL NFS Nagios Network Nginx OSSEC OTRS Observability Office OpenSearch PHP Perl Personal PostgreSQL PowerDNS Proxmox Proxy Python Rancher Rant Redis Roundcube SSL Samba Seafile Security Shell SmartOS Solaris Surveillance Systemd TLS Tomcat Ubuntu Unix VMWare VMware Varnish Virtualization Windows Wireless Wordpress Wyse ZFS Zoneminder Linux