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.
The last non-Dart layer
Section titled “The last non-Dart layer”| Layer | Already 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.
Terraform stays the execution layer
Section titled “Terraform stays the execution layer”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.
Dart types where HCL cannot help
Section titled “Dart types where HCL cannot help”Three concrete patterns where the Dart type system catches what HCL cannot:
Enums for fixed-value fields
Section titled “Enums for fixed-value fields”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 errorSealed 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.
Final classes for Stack subclasses
Section titled “Final classes for Stack subclasses”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.
How it fits next to other IaC
Section titled “How it fits next to other IaC”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.
| TerraDart | HCL | CDKTF | Pulumi | |
|---|---|---|---|---|
| Dart authoring | Yes | No | No | No |
Drop-in for terraform apply | Yes | Yes | Yes | Different model |
| Curated Dart factories | Yes | No | No | No |
| Project status | Alpha | Mature | Archived 2025 | Active |
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.
Curated provider coverage
Section titled “Curated provider coverage”terradart_googlewraps the GA HashiCorpgoogleprovider catalog — 1337 curated resource factories + 461 data sources (1798 catalog entries).terradart_google_betawraps beta-only types (128 resource factories).terradart_appwritewraps officialappwrite/appwriteprovider resources (filled at2.0.0-beta.1: 38 resource factories + 24 data sources).terradart_cloudflarewraps officialcloudflare/cloudflareprovider resources (filled at5.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.
Non-goals
Section titled “Non-goals”- 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 sameterraform apply.
Next steps
Section titled “Next steps”- Architecture —
synth()/writeTo(), provider integration, AppExport - Getting Started — install and first
*.tf.jsonoutput - How it’s built — generation pipeline, verification, sustainability
- Status — alpha expectations