The Config Report

The Config Report

Infrastructure as Code: Declarative vs Imperative (And Why Your Automation Still Breaks)

IaC Series – Issue 2 of 6: When Your Network Becomes Software

JJ – Chief Packet Pusher's avatar
JJ – Chief Packet Pusher
Mar 30, 2026
∙ Paid

The Moment Everything Gets Confusing

You start automating your network.

At first, it feels great.

No more clicking around in GUIs.
No more late-night “what changed?” guessing games.

You write a script like this:

  • Create VLAN 20

  • Assign ports

  • Enable trunk

Boom. Automation.

You sit back, sip your coffee, and think:

“Yeah… I’m basically DevOps now.”

Then something weird happens.

You run the same script again…
And now things break.


The Problem You Didn’t Know You Had

Your script isn’t wrong.

It’s just… bossy.

This is what we call imperative automation.

You’re telling the network:

“Do these exact steps. In this exact order. No questions.”

And the network is like:

“Cool… but I already did some of that.”

Now you’ve got:

  • Duplicate configs

  • Unexpected errors

  • Or worse… silent failures

Your automation didn’t fail.

It did exactly what you told it to do.

That’s the problem.


Imperative vs Declarative (The Real Difference)

Let’s make this painfully clear.

Imperative (What most network engineers start with):

create vlan 20
assign ports
enable trunk

You are controlling how the network gets there.

Step by step. Like a checklist.


Declarative (What IaC actually wants):

vlans:
  - id: 20
    name: users

You are describing what the network should look like.

Not how to build it.


Here’s the simplest way to think about it:

  • Imperative: “Do these steps.”

  • Declarative: “This is the outcome — figure it out.”


Why Your Scripts Break (Even When They’re “Correct”)

Imperative automation assumes one dangerous thing:

The starting state is always what you expect.

It’s almost never true.

Real networks have:

  • Old configs nobody remembers

  • Manual changes at 2AM

  • “Temporary” fixes from 6 months ago

  • That one engineer who “just tweaked something real quick”

So when your script runs:

  • Maybe VLAN 20 already exists

  • Maybe ports are already assigned

  • Maybe the trunk is already enabled

Now your script either:

  • Errors out

  • Overwrites something it shouldn’t

  • Or quietly does nothing useful


Declarative Thinking Changes Everything

Declarative systems don’t care how things got messed up.

They only care about one thing:

“Does the current state match the desired state?”

If not… fix it.

If yes… do nothing.

That’s why declarative automation is:

  • Idempotent (safe to run over and over)

  • Predictable

  • Much harder to break at scale


Controllers, Templates… and the IaC Confusion

This is where things get a little awkward.

Because a lot of network engineers think:

“We already have templates. We’re basically doing Infrastructure as Code.”

And to be fair… you’re not wrong.

Tools like:

  • Panorama device groups

  • Aruba Central group configs

  • Meraki network templates

Absolutely make your life better.

They give you:

  • Consistency

  • Centralized management

  • Less copy/paste chaos

Compared to pure CLI chaos, that’s a huge step forward.


But Here’s the Problem

They’re not actually Infrastructure as Code.

They’re centralized configuration.

And that’s not the same thing.

Because in most environments:

The source of truth is still the controller UI.

Which means…

  • Someone logs into the controller

  • Makes a quick change

  • Clicks commit

  • Moves on with their day

And just like that:

  • The network changed

  • Nobody reviewed it

  • Nothing was versioned

  • No one knows why it changed next week


This Is Still Imperative Thinking (Just With a GUI)

Even with templates, you’re still doing this:

“Go into the controller and make this change.”

That’s imperative.

You’re still telling the system how to change, not defining what it should be.


What IaC Actually Changes

Infrastructure as Code flips the model.

Instead of this:

“Log into the controller and update the template”

You do this:

  • Define config in a repo

  • Submit a change

  • Review it

  • Merge it

  • Let automation push it

Now the flow becomes:

Code → Automation → Controller → Devices

Not:

Engineer → Controller → Hope nothing breaks


The Controller’s New Job

In IaC, the controller doesn’t disappear.

It just gets demoted a little 😄

It becomes:

A deployment platform — not the source of truth


Why This Matters More Than People Realize

Because without this shift, you still have:

  • No real version control

  • No safe rollback

  • No audit trail that actually helps

  • No guarantee your “template” matches reality

You’ve improved consistency…

But you haven’t solved control.


⚠️ Where This Starts Getting Interesting

Because once you stop telling the network how to change…

And start defining what it should be…

You run into a new problem:

How do you actually enforce that state safely?


🔓 What Paid Subscribers Get in This Issue

If your automation only works when you babysit it…
this is the part you don’t want to miss.

In the rest of this issue, I break down:

  • How to make imperative tools (like Ansible) behave like declarative systems

  • The 3 rules that turn fragile scripts into safe, repeatable automation

  • Real-world patterns for checking state before making changes

  • How to stop writing “run once and pray” automation

  • Why most network automation fails silently—and how to fix it

This is the difference between:

“I have scripts”

and

“I have automation I actually trust in production”

Keep reading with a 7-day free trial

Subscribe to The Config Report to keep reading this post and get 7 days of free access to the full post archives.

Already a paid subscriber? Sign in
© 2026 JJ from The Config Report · Publisher Privacy ∙ Publisher Terms
Substack · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture