A Reddit thread making the rounds lately (“Best Infrastructure as Code Tools in 2025”) sparked a pretty good discussion around what teams are actually using for IaC right now. People threw in opinions on Crossplane, Pulumi, CDKTF, OpenTofu, and Ansible, and predictably, Terraform got a lot of airtime, especially with the license change and OpenTofu stepping in.

reddit post on best IAC tools in 2025

Tools have matured. Every option in that thread is ready for production. Some teams prefer YAML simplicity (Ansible). Others want strong typing and native languages (Pulumi, CDKTF). Many stick with HCL via Terraform or move to OpenTofu. But nobody's waiting for tooling to “catch up” anymore; they’re already good enough.

The real problem is what’s not codified.

Most orgs I’ve worked with have Terraform repos sitting in GitHub. Great. But then you poke around in their AWS accounts and find dozens of S3 buckets, IAM roles, or security groups that aren’t in any repo. Someone created them in the console or through a script that’s long gone. They’re in production, but no one owns them in code.

This is the real gap: infrastructure coverage and control. IaC adoption is high, but codification is still patchy. You’ve got a codebase that knows about some of your infrastructure, and the rest is invisible. And when infra is invisible, it’s unmanaged, no Git history, no review process, no policies, no disaster recovery plan.

That’s what this blog is about.

We’re going to break down what codified infrastructure actually means in 2025, what high-maturity teams are doing differently, what metrics they track, and where most orgs fall short. We’ll also look at how Firefly helps teams close that codification gap, pulling in unmanaged infra, catching drift, and making Git the source of truth again.

Let’s get into it.

The State of IaC in 2025 – IaC Usage Is High, Codification Is Still Low

It’s 2025, and Infrastructure-as-Code is everywhere. Terraform, Pulumi, CDKTF, OpenTofu, every team has at least one of them running in production. The market shows the same trend: according to 360iResearch, the IaC market is valued at $1.74 billion in 2024, expected to hit $2.22 billion in 2025, growing at a 27.7% CAGR. MarkWide Research projects a 25%+ CAGR through 2030. The point is clear: adoption isn’t slowing down.

But usage doesn’t equal codification. Just because you have a Terraform repo doesn’t mean your infrastructure is fully managed. In practice, I keep seeing the same pattern: most orgs only have about 40–60% of their actual infrastructure codified and governed through Git-based workflows. The rest? It’s outside the repo,  unmanaged, modified manually, or just plain invisible.

Where Codification Breaks Down

  • Manual console changes: Devops or Site Reliability Engineers make urgent tweaks in the AWS Console, maybe opening up a security group or updating a Lambda config. It solves the immediate problem, but no one backfills that change into Terraform or Pulumi. Now, infra state has diverged from code.

  • Multi-cloud drift: Teams operating across AWS, GCP, and Azure often handle each cloud differently. Maybe AWS is well-managed through IaC, but GCP resources get spun up manually or scripted in Bash. Over time, environments fall out of sync. You can't reason about them as a single system anymore.

  • SaaS configurations not managed in code: GitHub repo settings, Okta group mappings, PagerDuty escalation policies, Datadog alerts, these aren’t optional anymore. They’re part of your stack, but 90% of the time, they’re configured by hand and never tracked in Git.

Why This Actually Matters

  • Git stops being the source of truth: If infrastructure can change without a PR, Git history becomes useless. Now you’ve got infrastructure that's live but invisible, no audit trail, no approval, no rollback plan.

  • Audit prep becomes a manual mess: When security or compliance comes asking, you can't just point them to a repo. You’re logging into cloud consoles, pulling screenshots, and hoping what’s deployed matches what you think is deployed.

  • Cloud migrations and DR slow to a crawl: Moving to another region or rehydrating a broken environment assumes everything is in code. If it’s not codified, you’re rebuilding infrastructure from scratch or relying on tribal knowledge, and neither scales.

Pulumi nailed this in their Platform Engineering Pillars: provisioning infrastructure declaratively isn’t enough. You need drift detection, guardrails, and policy enforcement built into the platform from day one, not patched on after something breaks.

And that’s the shift. In 2025, IaC isn’t about provisioning anymore; it’s about governing infrastructure as a system. Codification is what makes that possible. If it’s not in code, you don’t control it.

What Firefly’s State-of-IaC 2025 Report Shows

Firefly’s latest State of IaC 2025 report surveyed multiple engineering teams across industries. The results back up what many of us already see on the ground:

Here’s how you can get the full report and see the insights for yourself. The snapshot below shows Firefly’s report download form. This has become a go-to resource for DevOps engineers, platform teams, and cloud architects looking to benchmark their Infrastructure-as-Code maturity across AWS, GCP, Azure, and hybrid environments:

state of IAC 2025

Here are some of the key findings from the report, and what they mean:

  • 89% of teams say they use Infrastructure-as-Code, but only 6% have full coverage across their environment. That means 94% of organizations still have parts of their infrastructure unmanaged, either manually provisioned, out of sync, or never codified at all.
  • 68% of teams operate in multi-cloud environments, but few have consistent codification across AWS, GCP, and Azure. Most teams manage each provider differently, which increases drift and makes centralized governance almost impossible.
  • 65% report that their cloud environments have become more complex in the past two years. More services, more accounts, more teams,  and no unified way to track or manage it all through code.
  • Only about one-third of organizations monitor drift continuously. The rest either check manually or wait until something breaks. That means changes made through the console or CLI can go undetected for weeks.
  • Automation-first CI/CD pipelines are emerging as a best practice, especially in teams that want to eliminate drift and enforce codification at the gate. Instead of relying on tribal knowledge and manual approvals, these teams build infra changes directly into PR workflows with testing, policy checks, and deployment steps automated.

This lines up with what I’ve seen firsthand: most orgs are “doing IaC” in name only. A Terraform repo that covers 50% of your infrastructure isn’t enough. The real benchmark is full coverage, continuous drift detection, and Git-based control across all clouds and SaaS platforms.

What Does “Codified Infrastructure” Actually Mean in 2025?

In 2025, just using Terraform or Pulumi doesn’t mean your infrastructure is codified. The bar is higher now. True codification means your entire infrastructure cloud, and SaaS is declared, versioned, enforced, and kept in sync through code. It’s not about the tool. It’s about coverage, control, and consistency.

Here’s what codified infrastructure really looks like today:

1. Everything is in Code, Cloud, and SaaS

It’s not just EC2s, VPCs, or GKE clusters. Codified infra includes GitHub repo permissions, Okta group rules, PagerDuty schedules, Datadog alerts, all the pieces that run your stack. If it affects production, it needs to be tracked in code. No exceptions.

2. Drift is Detected and Fixed Automatically

Tools need to continuously check your cloud state against the IaC source. If something drifts,  say, a security group rule added in the console, that needs to be caught. Ideally, a GitHub PR is opened with the fix. This isn’t a weekly report; it’s continuous, across every environment.

3. All Changes Go Through Git

If you’re still tweaking settings in the console, you’re not codified. Every change must start with a pull request, get reviewed, go through CI checks, and get deployed through automation. That’s GitOps. It’s not just good practice, it’s your audit trail, rollback plan, and disaster recovery baseline.

4. Policies Are Enforced Before Deploy

Security and compliance aren’t review checklists anymore; they’re enforced in the pipeline. Use tools like OPA or Sentinel to block PRs that violate org policies. Wrong region? Missing encryption? Over-provisioned instance? The CI should catch it and fail the build.

5. Code is Modular, Clean, and Can Be Auto-Generated

If your Terraform files are 2,000 lines long and duplicated across staging and prod, you’re doing it wrong. IaC should be reusable: use modules, variables, outputs, and dependency graphs. Tools like Firefly can scan your environment and automatically generate clean, import-ready code to fill in the gaps, especially for legacy or manually created resources.

How Firefly Classifies Infra

To help teams understand what’s actually codified and what’s not, Firefly uses a simple but effective model:

  • Codified: The resource is live in the cloud and defined in code. No drift. IaC is the source of truth.
  • Unmanaged: It exists in the cloud but isn’t in any repo. Someone likely created it manually, and it’s invisible to your pipeline.
  • Configuration Drift: It’s in both code and the cloud, but they don’t match. Maybe someone hotfixed it in the console. It’s now out of sync and risky.
  • Ghost drift: It’s in the state file, but no longer exists in the cloud. Probably deleted manually without cleaning up the state.

This framework gives you a concrete way to audit your environment and prioritize what needs fixing. You can't improve what you can't see, and most teams are surprised by how much infra falls into the "unmanaged" or "drifted" category when they first run a scan.

2025 Codification Benchmark: What High-Maturity Teams Achieve

In 2025, teams have gone far beyond writing basic Terraform files or automating EC2 creation. They’ve built structured, resilient, and secure systems where every piece of infrastructure,  cloud, or SaaS is tracked in code, tested in CI, governed by policy, and continuously reconciled with the live state.

Here’s a breakdown of what those teams do differently, based on what’s working in production today:

Capability Most Teams Today Fully Codified (Benchmark)
IaC Coverage 40–60%, infra only >90%, infra + SaaS
Drift Management Manual scripts Continuous + PR remediation
Policy Enforcement Ad hoc/manual reviews Auto-enforced PaC before deploy
IaC Authoring Handwritten HCL AI-assisted, modular, reusable, Self-Service
Infra Change Flow Mix of console + Git All Git-based, versioned
Cloud Coverage Single-cloud focus Multi-cloud + SaaS visibility

IaC Coverage

Most teams cover part of their infrastructure, usually core compute, storage, and networking. But configurations for things like GitHub permissions, Datadog monitors, Okta rules, or PagerDuty alerts are often unmanaged.

High-maturity teams declare everything in code. That includes cloud resources and SaaS configurations. If it touches production, it’s tracked in Git. This prevents hidden resources, unreviewed changes, and drift across tools.

Drift Management

Drift is usually managed by hand, maybe someone runs terraform plan once in a while, or an alert surfaces something out of sync. Most teams don’t have a continuous process.

Fully codified teams automate drift detection and remediation. Tools like Firefly compare live state against IaC definitions on a schedule or continuously. When drift is detected, the system either creates a GitHub PR to reconcile the change or auto-reverts it for protected resources. No manual digging, no surprises.

Policy Enforcement

Many teams rely on humans to catch policy violations, things like open ports, untagged resources, or unencrypted volumes. That’s inconsistent and error-prone.

Teams use Policy-as-Code (PaC) to enforce rules during CI. Tools like OPA (via Conftest), Sentinel, or Firefly Guardrails check every PR against codified policies. These rules block misconfigured infrastructure before it ever reaches the cloud. No exceptions. This also helps them stay compliant with standards like CIS, SOC 2, or GDPR.

IaC Authoring: AI-Assisted, Modular, Reusable

Writing Terraform manually often leads to duplicated logic, inconsistent patterns, and files that are difficult to maintain, especially across large teams or environments. High-maturity teams avoid this by standardizing on reusable modules and automating code generation wherever possible.

Firefly’s Self-Service supports two practical methods to generate clean, production-ready infrastructure code:

  • Module Call: Select any public or internal Terraform module, fill out the input variables with built-in validation and descriptions, and Firefly generates a ready-to-use module block. This is ideal when you have a predefined VPC, EC2, or RDS module and just want to reuse it across environments with consistent inputs.

  • Generate with Thinkerbell AI: Describe the infrastructure in plain language, for example, “Create a public EC2 instance with a security group that allows SSH and HTTP.” Firefly returns working Terraform, Pulumi, or CloudFormation code with variable blocks, dependencies, and tagging already handled.

Both flows let you push code directly to Git as a pull request. There’s no manual file copying, just versioned, peer-reviewed IaC integrated with your team’s workflows. This keeps your codebase consistent and reduces the long-term maintenance burden that comes with ad hoc or manually-written infrastructure code.

Infra Change Flow: All Git-Based, Versioned

In lower-maturity setups, changes happen in Git sometimes, but many changes are made directly in the console or CLI. That breaks auditability and makes rollback difficult.

In a fully codified infrastructure, teams make most of the changes via VCS (e.g., GitHub). Engineers open a pull request, CI runs validation, security, and policy checks, and approved changes are merged and applied. Console access is restricted or monitored, and changes outside Git are automatically flagged by drift detection. This is what real GitOps for infra looks like.

Cloud Coverage: Multi-Cloud + SaaS Visibility

Most teams are focused on a single provider,  usually AWS, with GCP, Azure, or SaaS left unmanaged or only partially scripted.

Teams use IaC consistently across multiple cloud providers and SaaS platforms. They don’t treat GCP, Azure, or internal tools as special cases. Everything goes through the same pipelines and policy engines. This standardization gives them a full picture of their stack, with no blind spots.

How Codifying Infrastructure Has Changed in 2025: It's Not About Writing Terraform Anymore

Most teams don’t start from scratch. You already have infrastructure live across AWS, GCP, Azure, Kubernetes, and a handful of SaaS platforms such as GitHub, Datadog, Okta, etc. The real problem is that most of that infrastructure was created outside of version control. Some of it was scripted once and diverged, or it’s been manually updated in the cloud console.

The challenge isn’t “choosing an IaC tool.” It’s bringing existing infrastructure under code-based control, safely, without breaking production.

This is exactly where Firefly fits in. Here’s how Firefly covers the main areas to keep your infrastructure codified all the time:

 Firefly covers the main areas to keep your infrastructure codified all the time


It doesn’t require rewriting the infrastructure from scratch. Instead, it scans what’s already running, identifies unmanaged resources, and generates clean, modular IaC, ready for production use.

Codify What’s Already Deployed

Firefly connects to your cloud and SaaS accounts, AWS, GCP, Azure, Kubernetes, GitHub, Okta, Cloudflare, and scans for unmanaged resources. It compares what’s deployed to what’s versioned and highlights gaps.

When Firefly scans your connected cloud accounts, it visualizes your infrastructure as a unified inventory. Every asset is labeled as Codified, Unmanaged, or Drifted.

Here’s what that looks like in the Firefly UI:

Firefly UI

In this GCP+AWS environment, out of 5,115 total resources:

  • Only 9 are currently codified (green).
  • 485 are unmanaged (red).
  • Others are drifted or ignored.

You can filter by cloud, asset type, tag, owner, or IaC status, making it easy to scope down to what matters for your next sprint.

For each unmanaged resource, Firefly can generate:

  • Terraform code with typed variables, tags, lifecycle rules, access control, and dependency relationships.
  • Pulumi, CDKTF, CloudFormation, Ansible, or Helm templates, depending on your stack.
  • Terraform import blocks (since Terraform 1.5) that let you adopt existing resources without touching them.

Let’s drill into a specific example, an unmanaged GCP compute instance called nginx-instance. It was created manually in us-central1-a and later terminated.

manually in us-central1-a and later terminated

Firefly shows:

  • The full ARN of the instance
  • Tags, termination status, and owner
  • Flags it as Unmanaged
  • And provides codification right from the UI

At the bottom, you can even see policy violations like "Cloud Waste" tied to governance rules, not just IaC status.

Clicking “Codify” in this instance opens Firefly’s IaC code generator. It creates a valid google_compute_instance block, along with the appropriate import block (supported since Terraform 1.5).

google_compute_instance[.code] block, along with the appropriate import block (supported since Terraform 1.5).
[.code]import {
  to = google_compute_instance.nginx-instance
  id = "projects/sound-habitat-462410-m4/zones/us-central1-a/instances/nginx-instance"
}
resource "google_compute_instance" "nginx-instance" {
  name         = "nginx-instance"
  machine_type = "e2-micro"
  ...
}

The import block ensures Terraform adopts the resource into state, without needing terraform import on the CLI. All metadata, disk mappings, labels, subnets, and project details are pre-filled correctly.

This means you can track it through Git, deploy it safely, and immediately start managing changes through PRs.

You can also push this generated code directly to any connected repo, with Firefly opening a pull request automatically. Just select the repo, click “Create,” and the unmanaged resource is now tracked in version control.

Just select the repo, click “Create,” and the unmanaged resource is now tracked in version control.

In this case, we’re pushing the nginx-instance code to aws-tcp-terraform repo, but you could push to any repo/workspace connected to your VCS provider (GitHub, GitLab, Bitbucket).

This allows you to adopt infrastructure into code, rather than re-provision or refactor in place.

Generate Modular Code, Not Flat Dumps

Firefly doesn’t just dump everything into a flat main.tf, which becomes a nightmare to maintain. Instead, it generates modular, structured, production-grade Terraform code.

Let’s take an example by prompting Firefly’s AI (Thinkerbell) with: “generate terraform template for an EC2 instance.”

The snapshot below shows exactly what Firefly returns, not just a basic script, but a clean, modular Terraform configuration you can push straight to production.

The snapshot below shows exactly what Firefly returns, not just a basic script, but a clean, modular Terraform configuration you can push straight to production.

The output includes:

  • main.tf with a properly structured aws_instance block, wired to a dedicated security group and subnet
  • variables.tf extracting inputs like AMI ID, instance type, key pair name, VPC/subnet IDs, and tagging values
  • outputs.tf exposing values like the EC2 instance’s ID, public/private IPs, DNS, and the security group ID
  • A user_data.sh bootstrap script that configures the EC2 instance as a basic web server

Firefly doesn’t just dump all resources into a single file. It structures Terraform code the way you’d expect in a real production repo: clean, modular, and easy to maintain.

  • Resources are grouped where they belong. For example, the EC2 instance sits right next to its security group, with properly scoped ingress and egress rules. You’re not dealing with a giant catch-all file where everything’s jumbled.
  • No hardcoded values. All inputs, like AMI ID, instance type, key name, VPC ID, and region, are pulled into variables.tf, so the code works across environments without rewrites.
  • Dependencies are set up correctly. The EC2 instance references the security group with .id, so Terraform applies them in the right order without you having to fix plan errors.
  • Outputs are clean and useful. Firefly includes key values like public IP, private IP, DNS, and security group ID in outputs.tf, which is exactly what you’d use in downstream modules or CI/CD workflows.
  • Modular by default. If you’ve got your own modules, Firefly integrates with them. If not, it generates reusable modules from scratch, no need to refactor a flat file later.

The code Firefly gives you isn’t something you have to clean up. It’s code you can version, push, and build on.

Module Call to Push IaC Changes

Firefly doesn’t just generate Terraform files; it integrates directly with your Git-based workflows and module structure. Here’s a snapshot of how Firefly handles module usage and GitOps in a real IaC workflow:

how Firefly handles module usage and GitOps in a real IaC workflow:

In this case, the module terraform-ec2-pipeline is selected directly from GitHub via Firefly’s Module Call interface. The input variable instance_type is configured as "t2.small", and Firefly generates the corresponding HCL:

module "terraform-ec2-pipeline" {
  source        = "github.com/bytebardshivansh/terraform-ec2-pipeline"
  instance_type = "t2.small"
}

Once the configuration is ready, Firefly integrates with GitHub to open a pull request. The setup includes selecting the repository, specifying the target branch, and optionally adding a PR comment (e.g., Changed the instance type from t2.micro -> t2.small).

This flow ensures infrastructure changes are version-controlled, peer-reviewed, and consistent with GitOps practices, with no manual steps, no drift, and no out-of-band changes.

Translate Infra Across Clouds

If you're aligning infrastructure across providers or setting up disaster recovery environments, Firefly can help you generate accurate cross-cloud equivalents, all while preserving clean, modular Terraform code.

Here’s what Firefly enables you to do:

  • Convert cloud-native resources across providers, e.g., convert an AWS EC2 instance to a GCP Compute instance or Azure VM, using the appropriate Terraform provider.
  • Maintain identical module interfaces across environments, even when the underlying resource implementations differ.
  • Build repeatable, environment-specific templates that use the same input variables and module interfaces, but plug in cloud-specific internals depending on the target platform.

Migrating GCP to AWS

This nginx-instance was originally deployed on a GCP Compute Engine VM. Using Firefly’s Cloud Migration capability, it was seamlessly converted into an AWS EC2 instance, with full Terraform module support.

Firefly:

  • Translated google_compute_instance into aws_instance
  • Preserved input variables like instance_name, volume_size, availability_zone, and more
  • Generated a structured Terraform module, not a flat dump

Here’s what the resulting AWS module looks like:

resulting AWS module

Use Codification Percent to Track Progress

Firefly calculates a Codification percent, a simple way to measure IaC maturity.

It’s based on:

  • Total resources discovered
  • % codified vs. unmanaged
  • Drifted resources
  • Policy violations (security, cost, compliance)

You can track this across accounts, clouds, and business units.

Firefly also includes IaC maturity checks:

  • Can you track 100% of the infrastructure in Git?
  • Are all infra changes applied via CI/CD?
  • Do you detect drift automatically?
  • Are policies applied before terraform apply or only after something breaks?

You can use this to prioritize cleanup, enforce org-wide standards, and report on maturity to stakeholders.

Here’s a real Firefly dashboard view summarizing codification, governance, and drift posture:

Firefly dashboard view summarizing codification, governance, and drift posture

This snapshot offers clear insight into the organization's infrastructure maturity. It highlights the need to address IaC gaps and increase codification coverage. With minimal ClickOps, teams are maintaining governance discipline, and cost optimization opportunities are becoming clearer. The metrics also support proactive compliance tracking, allowing teams to maintain high standards of security and operational integrity while scaling their IaC footprint.

FAQs

What is Cloud Automation?

Cloud automation is the use of code and tools to manage cloud resources automatically, including provisioning, configuration, scaling, and teardown, without manual effort. It’s usually done with IaC, CI/CD, and GitOps workflows.

What Are the Types of Cloud Automation?

Key types include infrastructure provisioning, configuration management, application deployment, security enforcement, and drift remediation. Each uses different tools but works toward consistent, hands-off infrastructure operations.

What is Cloud Automation Testing?

Cloud automation testing validates infrastructure changes before deployment. It includes unit tests (e.g., Terratest), integration tests, security scans (e.g., tfsec), and policy checks, all run in CI to catch issues early.

What is Cloud Deployment Automation?

Cloud deployment automation pushes infra or app changes to production using CI/CD pipelines. IaC tools provision the infrastructure, while apps are deployed via containers or orchestrators like Kubernetes or ArgoCD.