OpenTofu kept Terraform's model under an open source license. These are the best alternatives in 2026, now that agents write most of the code.
OpenTofu was created to keep Terraform's model open: the same HCL, providers, modules, state, and plan-and-apply workflow, under an open source license instead of a source-available one. That settled the licensing question, but it left the workflow exactly as it was, built for engineers who write and review every line of infrastructure by hand. So what happens when you bring agents into the mix? Recent research into AI-native delivery shows they have increased code output far faster than teams have increased how often they ship, while the infrastructure underneath still expects the same hand-authored config. This is what this new bottleneck looks like now:
In practice, bringing AI into the development cycle does raise code and feature output, but those gains keep running into the infrastructure problems underneath. They tend to show up as some, if not all, of these:
Encore is a platform for automating infrastructure from local development to cloud deployment. Instead of describing application architecture in separate infrastructure files, you declare services, APIs, and infrastructure resources in application code. Encore uses those declarations to run the application locally, validate it, and provision the infrastructure it needs in your own AWS or GCP account, without giving up control over how each environment is set up.
The difference is easiest to see on a single resource. In OpenTofu, a Postgres database means describing the instance and everything it depends on; in Encore, the application just declares what it needs:
OpenTofu
resource "aws_db_instance" "users" {
identifier = "users-db"
engine = "postgres"
instance_class = "db.t3.micro"
allocated_storage = 20
db_name = "users"
username = var.db_username
password = var.db_password
# ... plus networking, IAM, secrets
}
Encore
const db = new SQLDatabase("users", {
migrations: "./migrations",
});
The same Postgres database, written in HCL for OpenTofu and declared in Encore.
At first it looks like a trade-off between configurability and simplicity, but in reality, it's the same level of control, just each in its own place. Encore, through static analysis (a fancy way of saying it reads your code without running it), infers what it needs from the declaration: the database, its migrations, which services use it, and the IAM that follows from that. How it runs, such as its instance size, storage, networking, and backups, is abstracted into your environment configuration, which stays outside the code you (or an agent) write. The advantage of this approach is that the same code can be used to run locally, in preview environments, and across different cloud providers.
encore run. The same declaration provisions the real bucket in production, so what runs locally matches what ships.A Pub/Sub topic, an object storage bucket, or a cron job (and the other primitives Encore supports) works the same way. When an agent adds one:
.tf files of subnets, security groups, and IAM for an agent to write and a reviewer to read line by line.encore run, the change runs against real infrastructure locally and in each preview environment, so an agent (or human) can verify how it behaves end to end before it reaches production.Encore is the strongest fit for teams that want to get the most out of AI agents without loosening the guardrails around production, building backend services on AWS or GCP where infrastructure has become the delivery bottleneck.
Adopting it also assumes your existing OpenTofu configuration can stay in place, still managing the shared, org-level, or unsupported infrastructure it already handles while Encore takes the application resources it supports. Encore connects to databases you already run, such as RDS and Cloud SQL, so the two run side by side.
See the migration guide for teams coming from an IaC tool.
Learn more about how Encore automates infrastructure →
Run in your terminal to get started locally.
Terraform is the tool OpenTofu forked from, and it remains the default infrastructure as code, with the largest provider ecosystem of any option here. You describe resources in HCL and Terraform plans and applies them against a state file it maintains, the same model OpenTofu kept. The same Postgres database is the same block of HCL:
resource "aws_db_instance" "users" {
identifier = "users-db"
engine = "postgres"
instance_class = "db.t3.micro"
allocated_storage = 20
db_name = "users"
username = var.db_username
password = var.db_password
# ... plus networking, IAM, secrets
}
An agent works with Terraform just as it would with OpenTofu. It can generate HCL fluently, but the change stays inert until someone runs terraform plan and terraform apply, and it runs against shared state a careless edit can corrupt. There is no way to stand the real infrastructure up locally and check the change in the dev loop, so the apply, usually against a live environment, is the first real test. Moving from OpenTofu back to Terraform changes the license and the vendor, not the workflow.
Terraform fits teams that want HashiCorp's commercial ecosystem, such as HCP Terraform and vendor support, and are comfortable with its source-available BSL license, the reason OpenTofu exists in the first place. The two have diverged since the fork, with features on each side the other lacks, so moving back is not always a straight swap. Either way, the workflow is the one you already have: a separate configuration behind its own state and its own apply.
Pulumi replaces HCL with a general-purpose language, TypeScript, Python, Go, C#, or Java, so infrastructure gets the same type checking, editor support, and reusable abstractions as the rest of your code. The same Postgres database reads as a normal object:
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const db = new aws.rds.Instance("app-db", {
engine: "postgres",
instanceClass: "db.t3.micro",
allocatedStorage: 20,
dbName: "app",
username: "postgres",
password: config.requireSecret("dbPassword"),
skipFinalSnapshot: true,
});
Pulumi Cloud manages state, secrets, and policy by default, or you can run the state backend yourself.
An off-the-shelf coding agent writes a Pulumi program as easily as any other code, but the program keeps its own state and its own pulumi up, so the change waits on a human or CI to preview and apply it. Until that apply runs, the agent has no running infrastructure to validate against in the dev loop. Neo, Pulumi's own infrastructure agent, takes on that step by proposing changes as pull requests, running pulumi preview to surface policy violations, and moving a change through preview, approval, and apply inside your existing access controls and policy-as-code rather than around them.
Pulumi is the strongest fit when HCL is the main thing you want to leave behind and you want to keep an explicit infrastructure program across many clouds, with Neo automating more of the work on top. Moving from OpenTofu means rewriting configuration as a program, though, and the infrastructure still has its own code, state, and deployment lifecycle, so Pulumi improves how that pipeline is written without folding it into application delivery.
AWS CDK lets you define AWS infrastructure in TypeScript, Python, Java, C#, or Go, using constructs that bundle several resources into reusable components. Instead of HCL and a state file, it synthesizes that code into a CloudFormation template, which AWS then deploys and tracks as a stack.
const db = new rds.DatabaseInstance(this, "Postgres", {
engine: rds.DatabaseInstanceEngine.postgres({
version: rds.PostgresEngineVersion.VER_16,
}),
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE3, ec2.InstanceSize.MICRO),
credentials: rds.Credentials.fromGeneratedSecret("postgres"),
vpc,
});
Constructs are ordinary code, so an agent authors them fluently, but the code is only the first phase. It has to be synthesized to CloudFormation and deployed with real credentials before anything exists, and the agent has to reason about a two-step path, source to template to stack, that it cannot see from the source alone. There is no local run against real infrastructure to validate the change first.
CDK fits teams committed to AWS who want a real language instead of HCL, with CloudFormation tracking stacks in place of a state backend. It stays inside AWS, though, with no path to GCP or Azure, so it is a narrower choice than the multi-cloud providers OpenTofu gives you today.
SST is a framework for building and deploying full-stack applications, mostly on AWS, with higher-level components, resource linking, and a console for inspecting what you shipped. It actually runs on Pulumi with Terraform providers underneath, which is what lets it reach past AWS and past CloudFormation's stack limits, but it wraps that in an app-developer experience.
// sst.config.ts
const vpc = new sst.aws.Vpc("MyVpc");
const db = new sst.aws.Postgres("MyDatabase", { vpc });
Infrastructure and application code live in one TypeScript project, so an agent editing an SST app touches both at once, and the components are declarative and easy to generate. Nothing provisions until sst deploy runs, though, and because it sits on Pulumi, the same state and drift concerns apply, so the change still passes through a separate deploy before it is real. There is no local run against real infrastructure to check it in the dev loop first.
SST fits TypeScript teams building serverless-heavy applications on AWS that want less infrastructure boilerplate and a tighter link between app and cloud. It is the closest of these tools to putting infrastructure beside application code, but it keeps a separate sst.config.ts, the Pulumi state backend underneath, and a deploy step, and it stays oriented around AWS.
Crossplane turns a Kubernetes cluster into a control plane for cloud infrastructure. You describe resources as Kubernetes objects, and Crossplane provisions and continuously reconciles them against AWS, GCP, or Azure, while Compositions let a platform team expose its own higher-level APIs to developers. Its second major version, which graduated within the CNCF in 2025, made those resources namespaced and lets Compositions build on any Kubernetes resource, not only Crossplane's own.
apiVersion: rds.aws.m.upbound.io/v1beta1
kind: Instance
metadata:
name: app-postgres
spec:
forProvider:
region: us-east-1
engine: postgres
instanceClass: db.t3.micro
allocatedStorage: 20
A managed resource is just YAML, which an agent generates easily, but it does nothing until it reaches a cluster whose control plane already has the matching CRDs and a credentialed provider installed. There is no local run or preview without that machinery, and provider field names drift between versions, so a mismatch only surfaces at apply and reconcile time.
Crossplane makes sense when Kubernetes is already your control plane and the goal is to hand developers a curated internal API, which is a platform engineering decision more than a simpler way to replace OpenTofu. Teams that do not already run Kubernetes take on the largest prerequisite of any option here, a cluster, provider packages, Compositions, and the reconciliation failures that come with them, all around the cloud resources themselves.
The right choice comes down to why you are leaving OpenTofu:
The five that keep a separate program or configuration keep its state and its apply along with it, so an agent can author the change but not make it real on its own. Encore is the one that folds that step into the application code, and it coexists with your existing OpenTofu setup for anything it does not cover. The quickstart is the fastest way to see the difference.
It depends on why you are leaving OpenTofu: Terraform for HashiCorp's commercial ecosystem, Pulumi or AWS CDK to get out of HCL, SST for serverless apps on AWS, Crossplane for teams already on Kubernetes, and Encore for teams adopting AI who want infrastructure to ship with the application code.
Agents can author configuration in any of them, since HCL, TypeScript, and YAML are all easy to generate. The difference is what happens next: with most, the change still waits on a separate plan, apply, or deploy, while tools built around agents provision infrastructure directly from the code the agent writes.
Mostly no. Terraform, Pulumi, AWS CDK, SST, and Crossplane each keep a separate program or configuration and a state store of some kind. Encore derives its model from your code, so there is no separate infrastructure state file to maintain.
No. The code declares what the application depends on, while environment settings like capacity, networking, and backups stay in separate configuration. It is the same control, just kept in two places.
Yes. Encore is built to coexist, taking the infrastructure it supports while your existing OpenTofu configuration keeps managing the rest, and it can connect to databases you already run such as RDS and Cloud SQL.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.