DEV Community

Miklos Halasz
Miklos Halasz

Posted on

Terraform: Infrastructure as Code or Just a Fancy Wrapper?

I developed a healthy skepticism for tools that claim to make life easier by abstracting "complexity". Terraform is one of those tools.

It’s become something of a standard in the DevOps world. And I get why—it’s clean, declarative, and integrates well into GitOps and CI/CD workflows. It tracks state, it has a vibrant ecosystem of modules, and it supports everything from AWS to VMware to local libvirt. But despite its power, Terraform isn’t magic. In fact, it’s often just a more elegant wrapper around the APIs and CLI tools I was already using.

Let’s talk about what Terraform does well, and more importantly, where the abstraction leaks.


A Unified Language—But Not Really

One of the biggest marketing points behind Terraform is its "unified language" for infrastructure. You're told you can write a VM definition once and simply switch providers—from local libvirt to AWS or GCP—without changing much.

But here's the reality: you will change almost everything.

The configuration syntax may be consistent in terms of how blocks and attributes are defined, but the actual resource models between providers are completely different. For a virtual machine, AWS expects an AMI ID and an instance type. Libvirt wants memory and CPU counts and a reference to a QCOW2 image. That’s not a minor difference. It’s a complete redefinition of what a "machine" even is.

In practice, you don’t get portability. You get familiarity with the tooling syntax, but you still have to learn every provider's API model. At that point, are you really gaining anything over just writing some shell scripts for virsh or awscli, especially if you're only using one platform anyway?

The Wrapper Dilemma

Terraform doesn’t manage infrastructure by itself. It's just a structured way to call the APIs of your underlying tools. Whether that’s the AWS EC2 API, the Proxmox REST interface, or the local libvirt sockets, it depends on "providers"—which are essentially plugins maintained by HashiCorp or the community.

That dependency chain introduces friction. If Proxmox changes something in its API and the provider hasn't caught up yet, you’re stuck. You either wait for a fix or fork the provider yourself. It could be frustrating when you're blocked from using a feature that is technically available, just not exposed yet in Terraform.

With traditional shell scripts, you’d just call the new feature directly. It may be ugly, but it works now. That immediacy is something that I miss when relying on Terraform.

Easier Than Bash, Until It’s Not

I’ll be honest: writing infrastructure logic in HCL (HashiCorp Configuration Language) is much more pleasant than hacking away at brittle Bash scripts with a million conditionals and jq parsers. Terraform gives you a structured, declarative way to define your environment. That’s a win.

But that only goes so far. The moment you need to express logic Terraform doesn't support natively—loops beyond what for_each or count can handle, or conditional resources that depend on multiple variables—you end up writing external tooling anyway. That’s when the clean declarative abstraction starts to feel a lot like YAML with lipstick.

State Management: A Blessing and a Curse

One of Terraform’s key strengths is that it tracks the state of your infrastructure. It knows what you created, what changed, and what needs to be destroyed. This makes terraform plan and terraform apply very powerful, especially when you're working in teams.

But that state file is also a liability. Lose it, and you're flying blind. Mismanage it, and you can destroy production resources. Using remote backends like S3 or Git backends helps, but the whole concept of syncing and locking state adds a layer of fragility that simply doesn't exist when you're managing things manually.

When Terraform Works Best

Despite my criticisms, I do use Terraform. It shines in environments where infrastructure is complex, distributed, and managed by teams. It’s excellent when used to define cloud resources, manage networking, integrate with CI pipelines, and implement GitOps workflows. The repeatability and visibility into planned changes are things no ad-hoc shell script can give you cleanly.

If you’re spinning up identical environments across dev, staging, and production, Terraform’s modules and workspaces are a godsend. And if your team spans different roles (devs, ops, SREs), the shared syntax helps build common ground.

Final Thoughts

Terraform is a powerful tool, but it’s not the abstraction layer it’s often sold as. It doesn’t free you from learning your infrastructure platform—in fact, it requires that you know the platform well enough to map its concepts into Terraform’s provider model.

It's not a silver bullet. It's an elegant tool for automating and tracking infrastructure, especially in cloud-native environments. But for someone like me, who grew up close to the bare metal and still sees the value in understanding what’s under the hood, Terraform is best thought of as a structured wrapper with lifecycle management—not a replacement for knowing how things work.

Use it when it fits, but don’t be afraid to reach for virsh, awscli, or even plain Bash when you need control Terraform doesn’t yet expose.

Top comments (1)

Collapse
 
neeraj_srivastava_664c3d3 profile image
Neeraj Srivastava

😂 What a heist, Miclos! Looks like you’re on a personal vendetta against Terraform—did it steal your lunch money or what? Jokes aside, I loved how you brought this up in such a hilarious way. Your presentation was crystal clear, with just the right amount of salt to keep it spicy. Thanks for sharing, and kudos—keep those posts coming!