Infrastructure As Code Is Wrong
Tags: cloud, terraform, programming, devops
Published: 2021-05-12 21:11:11


There are several [problems in computer science that are very hard](https://www.martinfowler.com/bliki/TwoHardThings.html). One of them is naming things. So it should no surprise when names make little sense.

One of the "bad" names is "[Infrastructure as Code](https://en.wikipedia.org/wiki/Infrastructure_as_code)". I think it misleads more than it reflects the idea. 

***

In the era of self-hosted systems, infrastructure was managed by directly handling hardware and manually setting configurations. This approach does not work any longer in the age of cloud computing. It does not scale, it is too slow, and too risky.

Instead, the "Infrastructure as Code" (IaC) represents a different idea - to represent infrastructure and configurations as machine- and human- readable text and then use automation to manage it. These tools can create infrastructure components as many times as we like, do it very fast, and make sure they all are exactly the same.
 
If we take for example Terraform, provisioning of EC2 instance will look something like [this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance):

```hcl
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"

  tags = {
    Name = "HelloWorld"
  }
}
```
 
It is human-readable (and writable), but it can also be processed by automation. Terraform will do all actual calls to AWS to provision the instance for us based on configurations in text files that we give it. Also, these files can be version-controlled. We can put them in git and track changes to infrastructure. 

Just like code, right? But is it really code? It surely looks like it, but does not feel like it to me. What is code? Code is logic. It is either a series of imperative commands, 

> `if this do that, else do the other thing` 

(C++, Java, Python, etc), or declarative computation pipelines 

>`take data, pipe it through this function and apply this function to result`

(Haskell, Elixir, Clojure, etc). 
But in case of IaC, we describe the desired state of infrastructure 

>`I want 2 EC2 instances with such and such properties` 

We don't specify how exactly to get them. We don't specify what APIs to call and in what order, we don't specify logic to handle dependencies between resources. Instead, we rely on Terraform (or CloudFormation) to figure that out and do it for us.
 
The actual logic, the code, is the tool, Terraform or CloudFormation. What we give it, that textual description of what we want, is rather *data*. 
 
***

I have seen people take the name "Infrastructure as Code" for the face value and treat it the same way as the actual code. They try to fit loops, conditional statements and other imperative constructs into it, as if it was Java or C#. And it usually ends up pretty badly.
 
We should be very clear about what IaC is all about. Terraform or CloudFormation are not programming languages, not even frameworks. IaC is about being able to declaratively say what infrastructure you need and then use tools that will figure out how to get it for you. Trying to fit extensive logic into it is like trying to dig the ground with an iPhone. It can do it to some extent, but it is not what it's all about.

***
 
Infrastructure as Code seems like a very misleading term to me. When using this approach, you don't write actual code (logic) that will create infrastructure. You create configuration files that contain data that says what the infrastructure should look like. You create data, not code. That's why in my mind, "Infrastructure as Code" is actually **Infrastructure as Data**.