-
Notifications
You must be signed in to change notification settings - Fork 286
Feature: CDK Language Support — Author Azure Infrastructure in Any Programming Language #7425
Description
Feature: CDK Language Support — Author Azure Infrastructure in Any Programming Language
Summary
Enable developers to define their Azure infrastructure in general-purpose programming languages (C#, TypeScript/JavaScript, Python, Go, etc.) and have all azd commands work transparently. Customers should never need to know about or care about Bicep — they simply author their infrastructure in the CDK language of their choice, and azd init, azd up, azd provision, azd provision --preview, azd deploy, azd down, etc. all just work.
Motivation
Today, azd supports two infrastructure-as-code options: Bicep and Terraform. While powerful, both are domain-specific languages that require developers to learn specialized syntax. Many developers would prefer to define their infrastructure using the same programming languages they already use for their application code.
Cloud Development Kits (CDKs) make this possible by letting developers use familiar languages and tooling — IDE IntelliSense, type checking, debugging, refactoring, testing, and package management — to define infrastructure. The CDK compiles to an intermediate representation (like Bicep or ARM templates) that cloud platforms understand.
Azure already has this capability: Azure.Provisioning lets C# developers define Azure resources using the same Azure SDK types they use in their application code. The Azure CDK project is extending this to TypeScript/JavaScript. Other languages can follow the same pattern.
The gap is in azd — there's no way to point azd at a .cs or .js file in your infra/ folder and have it just work. This proposal would close that gap.
User Experience
What it looks like today (Bicep only)
my-app/
├── src/ # Application code
├── infra/
│ ├── main.bicep # Must learn Bicep DSL
│ ├── main.parameters.json
│ └── modules/
│ ├── cosmos.bicep
│ └── appservice.bicep
└── azure.yaml
What it should look like (CDK — C# example)
my-app/
├── src/ # Application code
├── infra/
│ └── infra.cs # Write infrastructure in C# — that's it
└── azure.yaml
Where infra.cs uses .NET 10 single-file app support (no .csproj needed):
#:package Azure.Provisioning.Resources@1.0.0
#:package Azure.Provisioning.Storage@1.0.0
using Azure.Provisioning;
using Azure.Provisioning.Resources;
using Azure.Provisioning.Storage;
var infra = new Infrastructure("helloStorage");
var rg = new ResourceGroup("rg");
infra.Add(rg);
var storage = new StorageAccount("storage")
{
Kind = StorageKind.StorageV2,
Sku = new StorageSku { Name = StorageSkuName.StandardLrs },
};
rg.Add(storage);
infra.Build().Save(args[0]);What it should look like (CDK — TypeScript example)
my-app/
├── src/ # Application code
├── infra/
│ └── infra.ts # Write infrastructure in TypeScript
└── azure.yaml
Where infra.ts uses the Azure CDK TypeScript API:
import { resourceGroup, stack } from "@azure-cdk/core";
import { storageAccount } from "@azure-cdk/storage";
const infra = stack({ name: "helloStorage", targetScope: "subscription" });
const rg = resourceGroup(infra, { location: "eastus" });
const storage = storageAccount(rg, {
sku: { name: "Standard_LRS" },
});All azd commands should work
| Command | Behavior |
|---|---|
azd init |
Detect CDK files in infra/, scaffold azure.yaml accordingly |
azd up |
Compile CDK → intermediate → deploy to Azure |
azd provision |
Same as above, infra only |
azd provision --preview |
Compile CDK → show what-if diff |
azd deploy |
Deploy application code to provisioned resources |
azd down |
Tear down all resources |
azd provision -- --param value |
Forward parameters to the CDK program |
Proof of Concept
We've built a working prototype for C# / Azure.Provisioning that demonstrates this is viable:
PR: #7352 — provider: code provisioning provider
CodeProvider— language-agnostic router that detects the CDK language from file extensions in/infraand dispatches to language-specific sub-providersDotNetProvider— compiles C# to Bicep viadotnet run, then delegates to the existingBicepProviderfor deployment- Auto-detection — drop a
.csfile in/infra, azd detects it automatically (no explicitprovider:config needed inazure.yaml) - Single-file support — uses .NET 10 file-based apps with
#:packagedirectives, no.csprojrequired - Parameter forwarding —
azd provision -- --region westus3 --prefix myapppasses args through to the C# program - Alpha-gated — behind
azd config set alpha.code on
Real-World Validation
We converted the todo-csharp-cosmos-sql sample template from Bicep to a single infra/infra.cs file: m-nash/todo-csharp-cosmos-sql-dotnet
- 7 Azure resources: Cosmos DB (serverless, NoSQL), App Service Plan, Web App, API App, Key Vault, App Insights, RBAC
- Full E2E verified:
azd up→ API responds → Playwright tests pass →azd downcleans up - Same app code, same tests — only the
/infrafolder changed
Azure CDK Playground
The Azure CDK project provides a web playground where users can write infrastructure in C# (and soon TypeScript) with full IntelliSense, see the compiled Bicep/JSON output in real-time, and get error diagnostics with line attribution — demonstrating the authoring experience.
Architecture
The proposed architecture uses a compilation step that converts CDK code to an intermediate representation before deployment:
CDK Source (.cs, .ts, .js, .py)
↓ [language-specific compiler]
Intermediate Representation (Bicep / ARM JSON)
↓ [existing azd deployment pipeline]
Azure Resources
This approach:
- Leverages existing azd infrastructure — all deployment, state management, and resource tracking reuse the proven Bicep/ARM pipeline
- Is language-extensible — adding a new CDK language means implementing a compiler adapter, not a new deployment pipeline
- Keeps Bicep as a supported first-class option — this is additive, not a replacement
Open Questions
1. Core Provider vs Extension
There are two viable implementation approaches:
Core Provider (current PR #7352 approach):
- New
ProviderKindinprovider.gowithCodeProviderrouting to language sub-providers - All
azdcommands work natively including--preview, parameter forwarding - Requires changes to azd core; ships with azd releases
azd Extension (suggested by @vhvb1989):
- Use
ServiceTargetProviderextension API to implement compilation + deployment - Ships independently from azd releases; no core changes needed
- Extension handles
Package()(compile CDK → Bicep) andDeploy()(deploy Bicep to Azure)
The extension approach may need some platform support to ensure all commands work seamlessly (e.g., --preview support, parameter forwarding). What's the preferred direction?
2. Language Onboarding
How should new CDK languages be added? The current architecture has a CodeProvider router that could dispatch based on file extension:
.cs/.csproj→ .NET / Azure.Provisioning.ts/.js→ TypeScript/JavaScript / Azure CDK.py→ Python (future).go→ Go (future)
Should each language be a separate azd extension, or should there be a single "CDK" extension/provider that bundles supported languages?
3. azd init Integration
When a user runs azd init, should there be an option to choose their CDK language? For example:
? Select your infrastructure language:
> Bicep
C# (Azure.Provisioning)
TypeScript
Terraform
4. Template Ecosystem
How should CDK-based templates be represented in the template gallery (aka.ms/awesome-azd)? Should there be CDK variants of existing templates, or should templates support multiple infrastructure languages side by side?
Related Work
- PR #7352 — Working prototype of
provider: codefor C# - Azure.Provisioning — C# CDK for Azure resources
- Azure CDK Playground — Web-based authoring environment with IntelliSense
- todo-csharp-cosmos-sql-dotnet — Real-world sample template using C# infrastructure (private, can be shared)