Contents

Infrastructure & Operations › Infrastructure as Code

Declarative vs Imperative Infrastructure

Describing the end state vs listing the steps.

Also known as: declarative vs imperative, declarative infrastructure, imperative infrastructure

There are two ways to tell a tool what you want. Imperative instructions list the steps: create this, install that, start the other, in order. Declarative configuration describes the end state you want, and the tool works out the steps to get there.

# imperative: a sequence of commands
gcloud compute instances create web-1 --zone us-central1-a
gcloud compute firewall-rules create allow-http --allow tcp:80
# declarative: the desired resources
resource "google_compute_instance" "web" {
  name = "web-1"
  zone = "us-central1-a"
}

The declarative form says what, not how. On each run the tool compares the real world to your description and changes only what differs — the basis of idempotence. That’s why Terraform, Kubernetes and Ansible feel declarative: you re-run them, and they converge rather than repeat.

The classic mistake is mixing the two without realizing it. Running imperative commands alongside a declarative tool means the tool sees changes it didn’t make and tries to undo them, or flags drift. Pick one source of truth.

Two more traps:

  • Expecting declarative tools to infer intent. If you rename a resource, the tool may see “delete old, create new” rather than “rename”, because it only knows states, not your reasoning. Plan for that.
  • Assuming order doesn’t matter. You still describe dependencies (this before that); the tool just figures out the rest.

When to use which: declarative for infrastructure you want to keep and reproduce — networks, clusters, environments. Imperative for genuinely one-off, sequence-sensitive scripts, like a data migration. Most modern infrastructure as code is declarative and lives in version control, often with a GitOps workflow.