Skip to content

Why TerraDart

If you read the landing page first: TerraDart keeps Terraform as the execution layer while you author infrastructure in Dart. This page goes deeper on motivation, the type system, and where TerraDart sits next to other IaC tools.

If your team ships Flutter on the client and Dart on the server (Cloud Run, Cloud Run functions, backend APIs), there is usually one layer left where Dart’s tooling does not reach: infrastructure definitions — often maintained in HCL, a Terraform-compatible pipeline, or cloud consoles. TerraDart closes that gap without asking you to give up Terraform itself.

LayerAlready Dart?
Mobile UI (Flutter)
Backend handlers (Cloud Run / Cloud Run functions / Shelf)
Application business logic
Infrastructure definitions❌ — HCL, Terraform-compatible tooling, or console

That bottom row is what people mean by the last non-Dart layer: everything above it shares dart analyze, refactors, and IDE navigation; infrastructure often does not.

A boundary held together by string literals

Section titled “A boundary held together by string literals”

Topic names typed in HCL or the console and again in your Cloud Run functions handlers. Renames do not reach subscribers via dart fix. IAM member strings drift with no compiler visibility. Infra values flowing into app code are often the place Dart’s type system never sees.

TerraDart pulls infrastructure into the same authoring surface as the rest of your code. dart analyze catches resource-name typos. Refactoring a Stack class is the same operation as refactoring any other Dart class. The same final / sealed discipline that already protects your domain model can protect your network topology.

TerraDart does not run terraform apply for you. It does not own your state file. It does not introduce a new provider or a new lock format.

What it does is take Terraform’s authoring model — provider blocks, resource blocks, references, lifecycle hooks — and express it as Dart code that generates the same *.tf.json Terraform would have accepted from HCL. terraform plan, terraform apply, and your remote state backend stay exactly where they are.

This is intentionally narrower than Pulumi, which has its own runtime, its own state model, and its own resource graph. With TerraDart the boundary is sharp: Dart is the authoring layer, Terraform is the execution layer. If you migrate off TerraDart tomorrow, your existing state and your existing modules are unchanged.

CDKTF used to occupy this same “code-first authoring of Terraform” niche, but only for TypeScript / Python / Java / Go — never Dart. CDKTF was archived in December 2025, leaving a Dart-shaped hole that TerraDart now fills.

Three concrete patterns where the Dart type system catches what HCL cannot:

Terraform schemas often have fields that accept one of a small, fixed set of strings — INGRESS_TRAFFIC_ALL vs INGRESS_TRAFFIC_INTERNAL_ONLY, for example. TerraDart emits these as Dart enums:

ingress: TfArg.literal(Ingress.all) // typo → compile error

Sealed classes for exactly-one-of nested blocks

Section titled “Sealed classes for exactly-one-of nested blocks”

Some Terraform blocks accept exactly one variant from a set — for instance, a BigQuery dataset’s access block has 8 mutually exclusive variants (user_by_email, group_by_email, special_group, domain, iam_member, view, dataset, routine). TerraDart emits these as a sealed class hierarchy:

access: [
Access.userByEmail(email: TfArg.literal("ops@example.com")),
Access.iamMember(member: TfArg.ref(runSa.member)),
]

The compiler enforces that exactly one variant is constructed per entry.

Stack, Resource, and Data are declared abstract base class since v0.11.0. Your own subclasses must use a class modifier:

final class AppInfraStack extends Stack { /* ... */ }

This prevents two foot-guns: forgetting to extend (using implements would skip the base-class state that synth needs), and accidentally subclassing an internal class that was not meant to be extended further. Both used to be runtime hazards in pre-v0.11 versions; they are now compile errors.

TerraDart fits teams already centered on Dart, already running Terraform (or a compatible pipeline) or managing infrastructure in cloud consoles, where the seam between infra and app code hurts.

TerraDartHCLCDKTFPulumi
Dart authoringYesNoNoNo
Drop-in for terraform applyYesYesYesDifferent model
Curated Dart factoriesYesNoNoNo
Project statusAlphaMatureArchived 2025Active

HCL has provider schema types; CDKTF bindings are typed in TypeScript and other languages. TerraDart’s difference is Dart-native authoring without replacing your Terraform execution pipeline.

HCL is the native, mature option. If your team is comfortable maintaining HCL alongside your Dart application code, there is no urgency to switch. TerraDart’s value proposition only matters once the cost of context-switching between Dart and HCL — and the absence of refactor / typecheck across that boundary — starts to bite.

CDKTF would have been the obvious model to follow, except it was archived by HashiCorp in December 2025 and never targeted Dart in any case. TerraDart is the Dart-shaped slot CDKTF did not reach.

Pulumi is a different model entirely: its own runtime, its own state, and its own resource graph. If your team is already invested in Pulumi and wants to author in Dart, consider Pulumi Dart (kingwill101/pulumi-dart), an active community language runtime for Pulumi. TerraDart is for teams who already use Terraform and want type-safe Dart authoring without replacing their Terraform state or execution pipeline.

TerraDart makes sense when you are already centered on Dart (Flutter + Cloud Run / backend apps), already using Terraform (or heading there), and the gap between those two — IaC stuck outside your Dart repo — is the part that hurts.

  • terradart_google wraps the GA HashiCorp google provider catalog — 1337 curated resource factories + 461 data sources (1798 catalog entries).
  • terradart_google_beta wraps beta-only types (128 resource factories).
  • terradart_appwrite wraps official appwrite/appwrite provider resources (filled at 2.0.0-beta.1: 38 resource factories + 24 data sources).
  • terradart_cloudflare wraps official cloudflare/cloudflare provider resources (filled at 5.23.0: 257 resource factories + 446 data sources).

The full factory list with example pointers is on Coverage; see also status and Architecture — Provider integration. Runnable stacks live in examples and the cookbook. Upgrading across minors? Read Migrating first.

  • Not a Terraform replacement — state and apply stay in Terraform.
  • Not a multi-cloud abstraction layer — wrappers faithfully mirror provider schemas rather than imposing cross-cloud abstractions.
  • Not a constructs framework in the pre-1.0 cycle.
  • Not module-block support — compose Terraform modules in HCL alongside TerraDart-generated *.tf.json; both feed the same terraform apply.