Declarative vs Imperative Infrastructure as Code

Sep 16, 2021 · 3 mins read · Post a comment

With the uprising of Terraform in the last couple of years, Infrastructure as Code (IaC) is a popular and hot topic in the DevOps world. Managing and deploying infrastructure is all what IaC is about.

It all started with configuration management, with tools like Puppet and Chef, and lately Ansible. Moving fast-forward, today we could notice these …as Code trendy practices almost everywhere, for example Compliance as Code, and this is a good thing. Why manage anything manually, when we could version code as a single source of truth, also known as the GitOps practices.

Okay, you get my point, now back to IaC. I’m pretty sure there a lot of blog posts out there that describes well the differences between the declarative and imperative approach when coding infrastructure. Let’s break them down in a simpler way.


From a declarative standpoint, you define the desired end state of the infrastructure, adding the resources you want, their configuration, and the IaC tool will figure out the rest.

Today, declarative IaC tools like Terraform, CloudFormation and ARM templates are among the most popular and used. Take for example the following Terraform code snippet:

resource "aws_lambda_function" "test_lambda_devcoops" {
  filename         = "devcoops_function_payload.zip"
  function_name    = "devcoops_lambda_function"
  source_code_hash = filebase64sha256("devcoops_function_payload.zip")

  runtime = "python3.8"

  environment {
    variables = {
      foo = "bar"

We declared a Lambda function including the argument’s filename, function_name, etc., and Terraform HCL will handle the rest under the hood. So, the key thing here is defining what we want, not how we want.

Few advantages to point out when using declarative approach:

  • Define only the desired end state.
  • Idempotency or running the code as much as times we want and getting the same results which leads to infrastructure consistency.
  • Easy to spot and deal with configuration drifts, by storing the current state (managing the state could be the only cons though).
  • Full version control compatibilities.

With that being said, Terraform is the current leader in the declarative IaC world. It uses the HashiCorp Configuration Language (HCL), which is a programming language wannabe. And recently they added Python and TypeScript SDK support, which will overcome some limitations of HCL itself.


On the other hand, with the imperative approach, we define and run the commands in a specific order, so the desired state could be achieved. This could be done with CLI tools and scripts, mostly. Take a look at AWS CLI for example:

aws s3 mb s3://devcoops-bucket --region eu-west-1

The imperative approach doesn’t store or manage any state, and if we run the same command over and over again, we might not get the same results.


So, which approach to choose?! It depends on your use-case scenario. If you need to manage infrastructure, go with declarative approach. I’m assuming you won’t be deploying everything from the CLI, that would be a total chaos. But, if you need to do a quick fix, CLI tool or a bash script would be the best choice.
Feel free to leave a comment below and if you find this tutorial useful, follow our official channel on Telegram.