Terraform in 2026: Why Most Teams Are Still Doing IaC Wrong (And How to Fix It)
By Joro Services · · Technical Services
Terraform has been around since 2014. Most engineering teams have been using it for years. And yet, the same problems appear in nearly every infrastructure codebase we look at. Not because the engineers don't know Terraform, because they do. But because good Terraform habits take more than just knowing the syntax.
Here's what we see consistently, and what to do about it.
The State File Is an Afterthought
Terraform state is the source of truth for your infrastructure. It's the file that tells Terraform what it has already built so it knows what to change, add, or destroy next time you run it.
The most common mistake we see is teams starting with local state. You run terraform init on your laptop, the state file lives in your project directory, and it works fine until it doesn't. Someone else on the team runs a plan and their state is different from yours. Or the state file gets committed to Git (which is a security risk because it contains sensitive values). Or it just gets deleted.
Remote state in S3 with DynamoDB locking for AWS is the fix, and it should be configured from day one, not retrofitted later. Retrofitting it is painful. Starting with it costs you about 20 minutes.
No Module Structure
The second most common issue is monolithic Terraform code. One big main.tf that contains every resource for the entire environment. It works when the environment is small. When the environment grows, plan times get long, every change touches the whole state, and the risk of accidentally destroying something you didn't mean to touch gets real.
Modules are how you solve this. Group related resources together (networking, compute, database, monitoring), each in their own module with clear inputs and outputs. Your root module then composes these modules together for each environment. Changes to your database module don't touch your networking module's state. Plans are faster. Risk is contained.
Environments Are Copied, Not Parameterised
We regularly see a staging folder that is an almost-identical copy of the production folder with a few values changed. When someone makes a change to production, they have to remember to make the same change to staging. When they forget, and they will forget, the environments drift apart.
The fix is to parameterise your infrastructure with variables and use either Terraform workspaces or separate state backends per environment, while sharing the same module code. One set of code, multiple environments. Changes flow through consistently.
No Drift Detection
Terraform plan tells you what changes would be made. But it only tells you when you run it. What it doesn't do by default is alert you when someone has manually changed something in the AWS console without going through Terraform, which is how drift happens.
Setting up scheduled plan runs in your CI pipeline that alert on any diff between your code and the real infrastructure is how you catch this. It's a simple pipeline job, but most teams don't have it.
Everything in One Workspace
Large infrastructure in a single Terraform workspace means a single state file managing hundreds of resources. Blast radius on any mistake is enormous. Plan and apply times are long. Locking one engineer out while another applies is a daily frustration.
Break your infrastructure into logical workspaces with separate state. Accept the overhead of managing multiple states. It's worth it.
The Bigger Point
None of these are exotic or difficult fixes. They're discipline and structure that most teams skip in the early days and then never go back to sort out. Technical debt in infrastructure is exactly as real as technical debt in application code. It just shows up differently, usually during an incident.
At Joro Services we do infrastructure reviews and help teams get their Terraform into a state where it's actually safe to use at scale. If you want a second pair of eyes on your IaC setup, get in touch.