📘

azure.yaml Reference

Your complete guide to azure.yaml - the configuration file that makes local development with azd app absolutely delightful

🎯What is azure.yaml?

Think of azure.yaml as your project's control center. It serves two purposes:

💻 Local Development (azd app)
Define services, health checks, logging, tests, and everything needed to orchestrate your local environment. Like docker-compose.yml on steroids!
☁️ Azure Deployment (azd)
Configure infrastructure, pipelines, and deployment to Azure. Supports Container Apps, App Service, Functions, AKS, and more!

This reference covers ALL properties - both for local development with azd appand Azure deployment with standard azd. It's the complete guide! 📚

Quick Start Example

Here's a minimal azure.yaml to get you started:

name: my-awesome-app
services:
web:
language: TypeScript
project: ./frontend
ports:
- "3000"
uses:
- api
api:
language: Python
project: ./backend
ports:
- "8000"

That's it! With just this, azd app will auto-detect your tech stack, figure out how to run your services, and set up health checks. Magic! ✨

🏷️name(required)

Your application's name. This is the only required field in azure.yaml. Keep it simple, descriptive, and URL-friendly!

PropertyTypeRequiredPatternLength
namestring✅ Yes^[a-z0-9]([-a-z0-9]*[a-z0-9])?$2-64 chars

Rules & Restrictions

  • ✅ Lowercase letters (a-z), numbers (0-9), hyphens (-) only
  • ✅ Must start and end with a letter or number
  • ✅ Length: 2-64 characters
  • ❌ No uppercase, spaces, special characters, or unicode
  • ❌ Cannot be empty or just whitespace
name: my-awesome-app # Letters, numbers, dashes, underscores (1-64 chars)
name: cool_project-2024 # ✅ Perfect!
name: my project # ❌ No spaces
name: "" # ❌ Can't be empty

🎭services

The services section is where the real party happens! 🎉 This is where you define all the different pieces of your application - web frontends, APIs, background workers, databases, caches, you name it.

🧠Smart Auto-Detection

azd app is pretty smart! It auto-detects your language, framework, and how to run your service based on files in your project directory. You often only need to specify projectand ports!

Service Types

Services come in different flavors depending on what they do:

🌐 http
Web servers, APIs, anything with HTTP endpoints. Default when ports are defined.
🔌 tcp
Raw TCP connections like databases, Redis, message queues.
⚙️ process
Background workers, queue processors. Default when no ports.
🐳 container
Docker containers. Auto-detected when image is set.
services:
# HTTP service - serves web content
web:
project: ./frontend
ports: ["3000"]
type: http # Default when ports are defined
# TCP service - raw socket connections (databases)
database:
image: postgres:16
ports: ["5432"]
type: tcp
# Process service - runs in background (workers, queues)
worker:
project: ./worker
type: process # Default when no ports defined
# Container service - Docker image
redis:
image: redis:7
type: container # Auto-detected when 'image' is set

Service Modes

Modes determine how azd app manages the service lifecycle:

🔄 daemon (default)
Long-running process that stays up. Most services use this.
👀 watch
Continuous file watcher (tsc --watch, nodemon). Monitors output for health.
🏗️ build
One-time build process that exits when done.
📋 task
Run manually on-demand (migrations, seeds).
services:
# Daemon - long-running server (default)
api:
project: ./api
mode: daemon
# Watch - continuous file watcher (TypeScript, Sass, etc.)
typescript:
project: ./frontend
command: tsc --watch
mode: watch
healthcheck:
type: output
pattern: "Found 0 errors"
# Build - one-time build that exits
assets:
project: ./frontend
command: npm run build
mode: build
healthcheck: false
# Task - runs on-demand only
migrate:
project: ./db
command: npm run migrate
mode: task

Complete Service Configuration

Here's the full power of service configuration with all available options:

services:
api:
# Core properties
language: TypeScript
project: ./backend
entrypoint: src/main.ts # Entry file
command: "tsx watch src/main.ts" # Override default command
type: http
mode: daemon
# Network
ports:
- "8080:8080" # host:container
- "127.0.0.1:9090:9090" # bind to specific IP
- "3000" # auto-map to same port
# Environment
environment:
- name: NODE_ENV
value: development
- name: DB_PASSWORD
secret: MY_DB_SECRET # Reference to secret
# Or as object (simpler for non-secret values)
# environment:
# NODE_ENV: development
# API_KEY: "abc123"
# Dependencies
uses:
- postgres
- redis
# Health monitoring
healthcheck:
type: http
path: /health
interval: 10s
timeout: 5s
retries: 3
start_period: 30s

All Service Properties

Complete reference of every property available for services:

PropertyTypeDefaultContextDescription
Core Properties (Local Dev - azd app)
languagestringauto-detectazd appProgramming language: js, ts, py, python, csharp, dotnet, go, java, rust, ruby, php, aspire
projectstring-BothRelative path to service source directory
entrypointstringauto-detectazd appEntry file (e.g., main.py, app.js, main.go)
commandstringauto-detectazd appOverride run command (e.g., "npm run dev")
typeenumhttp/processazd appService type: http, tcp, process, container
modeenumdaemonazd appRun mode: daemon, watch, build, task
imagestring-BothDocker image name. Mutually exclusive with project in some contexts.
portsarray-azd appPort mappings: ["3000"], ["3000:8080"], ["127.0.0.1:3000:8080"]
environmentarray/object-azd appEnvironment variables as array of {name, value/secret} or key-value object
usesarray-BothArray of service/resource names this depends on. Auto-detected by azd app init
dockerobject-BothDocker build configuration (see Docker section)
healthcheckobject/boolautoazd appHealth check config or false to disable
logsobject-azd appService-level logging configuration
testobject-azd appService-level test configuration
Deployment Properties (azd)
hostenum-azdRequired for deployment. Azure service type: appservice, containerapp, function, springapp, staticwebapp, aks, ai.endpoint, azure.ai.agent
resourceGroupstringdefault RGazdOverride resource group for this service
resourceNamestringauto-discoverazdOverride Azure resource name
apiVersionstringlatestazdResource provider API version (Container Apps only)
modulestringservice nameazdInfrastructure module path relative to infra folder
diststring-azdRelative path to deployment artifacts
k8sobject-azdKubernetes configuration for AKS deployments
configobject-azdHost-specific configuration (AI endpoints, agents, etc.)
envobject-azdEnvironment variables for deployment (key-value pairs)
localobject-azd appLocal development configuration including customUrl
azureobject-azdAzure deployment configuration including customUrl and customDomain
hooksobject-azdService-level hooks: predeploy, postdeploy, prerestore, postrestore, prebuild, postbuild, prepackage, postpackage, prepublish, postpublish

Service URL Configuration

Configure custom URLs for accessing your services through the local and azure configuration objects. These URLs are used when the actual access point differs from the auto-discovered service URL.

PropertyTypeContextWritableDescription & Examples
local.urlstringLocal devReadonly
Auto-discovered local URL (NEVER overridden). Always shows the actual localhost endpoint.
Examples: http://localhost:3000, http://localhost:8080
⚠️ If service has custom URL, both URLs are preserved separately
local.customUrlstringLocal devYes
Custom URL for accessing the service (used for display). The original localhost URL is preserved in local.url.
Examples: https://myapi.ngrok.io, http://myapp.local:8080
azure.urlstringAzureReadonly
Auto-discovered Azure URL (NEVER overridden). Always shows the actual provisioned endpoint.
Examples: https://myapp.azurewebsites.net, https://myapi.azurecontainerapps.io
⚠️ If service has custom domain, both URLs are preserved separately
azure.customUrlstringAzureYes
Custom URL for Azure deployment (used for display). The original Azure URL is preserved in azure.url. Typically used with CDN/Front Door.
Examples: https://www.contoso.com, https://api.fabrikam.com/v1
azure.customDomainstringAzureYes
Custom domain name for Azure deployment (domain only, no protocol). Converted to HTTPS URL for display. The original Azure URL is preserved in azure.url.
Can be auto-discovered from Azure resource settings (e.g., App Service custom domain) or set locally in azure.yaml.
Examples: www.contoso.com, api.fabrikam.com
⚠️ Do not include http:// or https://

Common Use Cases

  • Custom domains: Users access via www.company.com instead of Azure-generated URLs
  • Development tunnels: Expose local services via ngrok or similar tools
  • Reverse proxies: Traffic flows through a gateway or load balancer
  • CDN endpoints: Content delivered via Azure Front Door or Cloudflare
  • API gateways: APIs accessed through Azure API Management
services:
# Local development with ngrok tunnel
api:
project: ./backend
ports: ["8080"]
local:
customUrl: https://myapi.ngrok.io
# Local URL shown as: https://myapi.ngrok.io
# Auto-discovered: http://localhost:8080
# Production with custom domain and CDN
web:
host: containerapp
project: ./frontend
azure:
customUrl: https://www.mycompany.com
customDomain: www.mycompany.com
# Access URL: https://www.mycompany.com
# Azure deployed to: https://web-abc123.azurecontainerapps.io
# API behind Azure API Management
backend:
host: containerapp
project: ./api
azure:
customUrl: https://api.mycompany.com
customDomain: api.mycompany.com
# Access URL: https://api.mycompany.com
# Azure deployed to: https://backend-xyz789.azurecontainerapps.io
# Both local tunnel and production custom domain
fullstack:
host: appservice
project: ./app
local:
customUrl: https://app.ngrok.io
azure:
customUrl: https://app.company.com
customDomain: app.company.com
# Local: https://app.ngrok.io
# Azure: https://app.company.com

🎯How It Works: URL Property Design

The system maintains two separate readonly URL properties that preserve the original auto-discovered endpoints. Custom URLs are stored separately and used for display purposes.

Local Development URLs:
  • local.url - Readonly, always preserves the original auto-discovered URL (e.g., http://localhost:3000)
  • local.customUrl - Optional user-configured display URL (e.g., https://myapi.ngrok.io)
  • Both URLs are preserved separately - you can always see the actual localhost endpoint AND the custom access URL
Azure Deployment URLs:
  • azure.url - Readonly, always preserves the original Azure endpoint (e.g., https://myapp.azurecontainerapps.io)
  • azure.customUrl - Optional user-configured display URL (e.g., https://www.contoso.com)
  • azure.customDomain - Optional domain name that converts to HTTPS URL (e.g., www.contoso.com → https://www.contoso.com)
  • Original Azure URL is never overwritten - both the provisioned endpoint and custom domain are preserved
🔒Readonly Properties

The local.url and azure.url properties are readonly and automatically set at runtime. You cannot directly set these in your azure.yaml. Instead, configurelocal.customUrl, azure.customUrl, orazure.customDomain to provide custom access URLs.

💡Example: URL Separation

services:
api:
project: ./backend
ports: ["8080"]
local:
customUrl: https://api.ngrok.io
azure:
customDomain: api.mycompany.com
# What happens at runtime:
# Local development (azd app run):
# - local.url = "http://localhost:8080" (auto-discovered, NEVER changes)
# - local.customUrl = "https://api.ngrok.io" (user-configured)
# - Display shows BOTH: "Access URL: https://api.ngrok.io" + "Local URL: http://localhost:8080"
# Azure deployment (azd deploy):
# - azure.url = "https://api-xyz123.azurecontainerapps.io" (auto-discovered, NEVER changes)
# - azure.customDomain = "api.mycompany.com" → converted to "https://api.mycompany.com"
# - Display shows BOTH: "Access URL: https://api.mycompany.com" + "Azure URL: https://api-xyz123.azurecontainerapps.io"
# Key Point: Original URLs are ALWAYS preserved alongside custom URLs

Display Behavior

  • CLI (azd app info): Shows both "Access URL" (custom) and original URL when they differ
  • Dashboard: Primary link uses the custom URL; hover/tooltip shows the original provisioned URL
  • Service Discovery: Environment variables reference the appropriate URL based on context
  • Logs: Both URLs included in startup messages for clarity and debugging

⚠️Important Notes

  • These properties are informational only - they don't configure DNS, SSL certificates, or routing
  • You must separately configure your infrastructure (custom domains, reverse proxies, CDN, etc.)
  • customUrl requires full URL with protocol (http:// or https://)
  • customDomain accepts domain name only (e.g., www.example.com) - can be auto-discovered from Azure or set locally
  • Used primarily for documentation, UX, and helping developers know both the actual provisioned endpoint and the custom access point

Environment Variable Formats

services:
api:
# Array format (supports secrets)
environment:
- name: NODE_ENV
value: development
- name: DB_PASSWORD
secret: DB_SECRET # Reference to secret
# Object format (simpler, no secrets)
environment:
NODE_ENV: development
API_URL: http://localhost:8080
DEBUG: "true"

❤️Health Checks

Health checks are how azd app knows when your services are actually ready to accept connections. No more "Connection refused" errors because you tried to hit your API before it finished starting up! 🎯

💡Pro Tip

Health checks are automatically configured for most services! HTTP services get HTTP health checks, containers with TCP ports get TCP checks, and process services get process checks. You only need to customize them if the defaults don't work for you.

Health Check Types

services:
# HTTP health check (default for HTTP services)
api:
ports: ["8080"]
healthcheck:
type: http
path: /health # Default is /health
interval: 30s
timeout: 10s
retries: 3
# TCP health check - checks if port is listening
database:
image: postgres:16
ports: ["5432"]
healthcheck:
type: tcp
interval: 10s
retries: 5
# Process health check - verifies process is running
worker:
project: ./worker
healthcheck:
type: process
interval: 15s
# Output health check - watches stdout for pattern
typescript-watcher:
project: ./frontend
command: tsc --watch
mode: watch
healthcheck:
type: output
pattern: "Found 0 errors\. Watching for file changes"
timeout: 60s
# Disable health check for build processes
build-assets:
project: ./assets
command: npm run build
mode: build
healthcheck: false
# Docker Compose style (cross-platform compatible)
postgres:
image: postgres:16
healthcheck:
test: "http://localhost:5432" # Preferred
# Or: ["CMD", "pg_isready", "-U", "postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 40s

Health Check Properties

PropertyTypeDefaultDescription
typestringhttp/processhttp, tcp, process, output, none
pathstring/healthHTTP endpoint path
patternstring-Regex pattern for output checks
intervalduration30sTime between checks
timeoutduration30sMax time for check
retriesinteger3Failures before unhealthy
start_periodduration0sGrace period on startup
disablebooleanfalseSet true to disable checks

🐳Docker & Containers

Run Docker containers alongside your code services! Perfect for databases, caches, Azure emulators, and any other infrastructure you need during development.

services:
custom-app:
image: myapp:latest # Use existing image
ports: ["8080"]
built-app:
docker:
path: ./Dockerfile # Path to Dockerfile
context: . # Build context
platform: linux/amd64
buildArgs:
- NODE_VERSION=20
- BUILD_ENV=production
registry: myregistry.azurecr.io
image: myapp
tag: v1.0.0
ports: ["8080"]

📦 Container Service Properties

  • image - Docker image name (makes it a container service)
  • ports - Port mappings in "host:container" format
  • environment - Environment variables for container
  • volumes - Persistent volume mounts
  • docker.path - Path to Dockerfile for building
  • docker.context - Build context directory
  • docker.platform - Target platform (linux/amd64, linux/arm64)
  • docker.buildArgs - Build-time arguments

All Docker Build Properties

PropertyTypeDefaultDescription
pathstring./DockerfilePath to Dockerfile relative to service project
contextstringproject dirBuild context directory. Use "../" for monorepo shared dependencies.
platformstringhost platformTarget platform: linux/amd64, linux/arm64, windows/amd64
registrystring-Override container registry (e.g., "myregistry.azurecr.io")
imagestringservice nameImage name (without registry/tag)
tagstringazd-{env}-{timestamp}Image tag. Use "latest" with caution in production.
buildArgsarray-Build arguments: ["NODE_ENV=production", "API_VERSION=v2"]
targetstring-Multi-stage build target (e.g., "production", "development")
remoteBuildbooleanfalseBuild in cloud (Azure Container Registry Tasks) for faster CI/CD

Check out the Container Services Guide for detailed examples and pre-built container configurations!

☁️resources

Define Azure resources your application uses in production. While this mainly affects deployment, it's useful for documentation and understanding your app's cloud dependencies.

resources:
# Azure Storage Account
storage:
type: Microsoft.Storage/storageAccounts
# Azure Key Vault
keyvault:
type: Microsoft.KeyVault/vaults
# SQL Server with dependency
sqlserver:
type: Microsoft.Sql/servers
uses:
- keyvault # Depends on key vault
# Existing resource (not provisioned by azd)
existing-db:
type: Microsoft.Sql/servers
existing: true

Resource Properties

  • type (required) - Azure resource type
  • uses - Other resources this depends on
  • existing - Set true for existing resources not provisioned by azd

All Resource Types

TypeAzure ServiceCommon Uses
azure.servicebus.namespaceAzure Service BusMessage queues, pub/sub messaging
azure.storage.accountAzure StorageBlob storage, file shares, queues, tables
azure.cosmos.accountCosmos DBNoSQL database, globally distributed
azure.sql.serverAzure SQL DatabaseRelational database (SQL Server)
azure.keyvault.vaultAzure Key VaultSecrets, keys, certificates management
azure.eventhub.namespaceEvent HubsBig data streaming, event ingestion
azure.redis.cacheAzure Cache for RedisIn-memory cache, session storage
azure.search.serviceAzure AI SearchFull-text search, vector search
azure.appinsights.accountApplication InsightsMonitoring, telemetry, diagnostics
azure.ai.modelAzure AI ModelAI/ML models (OpenAI, etc.)
azure.ai.projectAzure AI ProjectAI project workspace
azure.containerapp.environmentContainer Apps EnvironmentContainer app infrastructure
azure.aks.clusterAzure Kubernetes ServiceKubernetes cluster orchestration
azure.container.registryAzure Container RegistryPrivate Docker image registry

Common Resource Properties

PropertyTypeRequiredDescription
typeenum✅ YesAzure resource type (see table above)
usesarrayNoNames of resources this depends on
existingbooleanNotrue if resource already exists (not provisioned by azd)
propsobjectNoResource-specific properties (varies by type)

reqs (Prerequisites)

Define prerequisite tools your project needs. azd app will check for these tools and their versions before running your application. No more "works on my machine" problems! 🎉

reqs:
# Simple version check
- name: node
minVersion: "20.0.0"
# With installation URL override
- name: python
minVersion: "3.11"
installUrl: "https://www.python.org/downloads/"
# Check if tool is running (Docker daemon)
- name: docker
minVersion: "20.0.0"
checkRunning: true
installUrl: "https://docs.docker.com/desktop/"
# Custom version check command
- name: my-tool
minVersion: "2.5.0"
command: my-tool
args: ["version"]
versionPrefix: "v" # Strip 'v' prefix
versionField: 1 # Which field has version
installUrl: "https://example.com/install"
# Custom running check
- name: kubernetes
command: kubectl
checkRunning: true
runningCheckCommand: kubectl
runningCheckArgs: ["cluster-info"]
runningCheckExpected: "Kubernetes control plane"
runningCheckExitCode: 0

🔍 Built-in Tools

azd app has smart defaults for common tools: node, python, docker, go, java, dotnet, rust, etc. Just specify the name and minVersion!

🛠️ Custom Tools

For custom tools, specify how to check the version with command,args, and parsing options.

All Requirement Properties

PropertyTypeRequiredDescription
namestring✅ YesTool name (node, python, docker, go, etc.)
minVersionstringNoMinimum required version (semver format)
commandstringNoCommand to run for version check (defaults: node --version, python --version, etc.)
argsarrayNoArguments for version command: ["--version"]
versionPrefixstringNoPrefix to strip from version string (e.g., "v" for "v1.2.3")
versionFieldstringNoField name if version is in JSON output
checkRunningbooleanNoAlso verify tool is running (e.g., Docker daemon)
runningCheckCommandstringNoCommand to check if running
runningCheckArgsarrayNoArguments for running check command
runningCheckExpectedstringNoExpected substring in output if running
runningCheckExitCodenumberNoExpected exit code if running (default: 0)
installUrlstringNoURL shown to user for installation instructions

Built-in Tool Names

These tools have automatic version detection and smart defaults:

nodepythondockergojavadotnetrustrubyphpazdkubectlterraform

🪝hooks (Lifecycle Hooks)

Run custom scripts before or after commands. Perfect for setup tasks, notifications, or custom workflows.

hooks:
# Simple pre-run hook
prerun:
run: npm install
shell: sh
# Post-run notification
postrun:
run: echo "🚀 All services are running!"
shell: sh
continueOnError: true # Don't fail if hook fails
# Pre-stop hook (drain connections before shutdown)
prestop:
run: echo "Draining connections..."
shell: sh
continueOnError: true
# Post-stop cleanup
poststop:
run: ./scripts/cleanup.sh
shell: bash
# Platform-specific hooks
prerun:
windows:
run: .\scripts\setup.ps1
shell: pwsh
posix:
run: ./scripts/setup.sh
shell: bash

Available Hooks

  • prerun - Runs before azd app run
  • postrun - Runs after azd app run
  • prestop - Runs before azd app stop
  • poststop - Runs after azd app stop

Hook Properties

  • run - Script or command to execute
  • shell - Shell type (sh, bash, pwsh, powershell, cmd)
  • continueOnError - Don't fail if hook fails
  • interactive - Bind to stdin/stdout
  • windows - Windows-specific override
  • posix - Linux/macOS override

All Hook Properties

PropertyTypeDefaultDescription
runstring-Command or script to execute
shellenumsh/pwshShell type: sh, bash, pwsh, powershell, cmd
continueOnErrorbooleanfalseContinue execution even if hook fails
interactivebooleanfalseAllow user interaction (stdin/stdout)
windowsobject-Windows-specific hook config (same properties)
posixobject-Linux/macOS-specific hook config (same properties)

Available Hook Types

HookContextTrigger
prerunazd appBefore azd app run
postrunazd appAfter azd app run
prestopazd appBefore azd app stop
poststopazd appAfter azd app stop
predeployazdBefore azd deploy
postdeployazdAfter azd deploy
prerestoreazdBefore azd restore
postrestoreazdAfter azd restore
prebuildazdBefore building service
postbuildazdAfter building service
prepackageazdBefore packaging service
postpackageazdAfter packaging service
prepublishazdBefore publishing to registry
postpublishazdAfter publishing to registry

📊logs (Logging Configuration)

Control log filtering, classification, and Azure Log Analytics integration. Keep your logs clean and organized!

Basic Logging

logs:
# Filter out noisy logs
filters:
exclude:
- "npm warn"
- "Debugger listening on"
- "ExperimentalWarning"
# Override log levels
classifications:
- text: "DEPRECATED"
level: warning
- text: "fatal"
level: error
- text: "panic"
level: error

Azure Log Analytics Integration

Stream logs from your deployed Azure services (Container Apps, App Service, Functions) directly into your local dashboard with Log Analytics integration. View local and cloud logs in one unified interface.

📘 Complete Azure Logs Guide

See the Azure Cloud Log Streaming reference for detailed setup, dashboard features, troubleshooting, and examples.

# Project-level: Configure polling behavior
logs:
analytics:
pollingInterval: 30s # How often to refresh Azure logs (default: 30s)
defaultTimespan: PT15M # Time range for queries (ISO 8601 duration, default: PT15M)
# Service-level: Specify Log Analytics tables
services:
web:
host: appservice
path: ./src/web
logs:
analytics:
table: AppServiceConsoleLogs # App Service standard table
api:
host: containerapp
path: ./src/api
logs:
analytics:
table: ContainerAppConsoleLogs_CL # Container Apps custom log table
functions:
host: functions
path: ./src/functions
logs:
analytics:
table: FunctionAppLogs # Functions standard table
# Advanced: Custom KQL query (yaml-only, not exposed in dashboard UI)
worker:
host: functions
path: ./src/worker
logs:
analytics:
query: |
FunctionAppLogs
| where FunctionName == "ProcessQueue"
| where TimeGenerated > ago(15m)
| where Level == "Error"
| order by TimeGenerated desc

Logging Features

  • Filters: Suppress noisy patterns with regex (case-insensitive)
  • Classifications: Override log levels based on text matches
  • Azure Analytics: Stream logs from Container Apps, App Service, and Functions
  • Unified Dashboard: View local and cloud logs in one interface with time range selection and service filtering
  • Custom KQL Queries: Advanced users can provide custom Kusto queries via azure.yaml
Note: Azure Log Analytics has 1-5 minute ingestion latency. Logs refresh automatically based on polling interval.

All Logging Properties

PropertyTypeContextDescription
Filter Configuration
filters.excludearrayGlobal/ServiceArray of regex patterns to suppress logs (case-insensitive)
classificationsarrayGlobal/ServiceOverride log levels based on patterns
Azure Log Analytics
analytics.enabledbooleanGlobal/ServiceEnable Azure Log Analytics integration
analytics.workspaceIdstringGlobal/ServiceLog Analytics workspace ID
analytics.tablestringServiceKQL table name (AppServiceConsoleLogs, ContainerAppConsoleLogs, etc.)
analytics.querystringServiceCustom KQL query (overrides default table query)
analytics.pollIntervalstringGlobal/ServicePolling interval (e.g., "5s", "30s", "1m")
analytics.streamingbooleanServiceUse real-time streaming when available (Container Apps)

Log Classification Properties

PropertyTypeValuesDescription
patternstringregexPattern to match in log text (case-insensitive)
levelenumdebug, info, warn, errorLog level to apply when pattern matches

🧪test (Testing Configuration)

Configure unit, integration, and e2e tests for your services. Run them all with azd app test!

# Global test configuration
test:
parallel: true # Run service tests in parallel
failFast: false # Continue even if a test fails
outputDir: ./test-results
outputFormat: junit # default, json, junit, github
coverage:
enabled: true
threshold: 80 # Fail if coverage < 80%
exclude:
- "**/vendor/**"
- "**/test/**"
services:
api:
test:
# Unit tests
unit:
command: npm test
path: tests/unit
pattern: "*.test.ts"
timeout: 5m
env:
NODE_ENV: test
# Integration tests
integration:
command: npm run test:integration
path: tests/integration
timeout: 10m
# End-to-end tests
e2e:
command: npm run test:e2e
path: tests/e2e
timeout: 15m
# Service-specific coverage
coverage:
enabled: true
threshold: 85
exclude:
- "**/*.test.ts"
- "**/mocks/**"

Testing Features

  • Multi-level: Unit, integration, and e2e tests per service
  • Parallel Execution: Run tests across services simultaneously
  • Code Coverage: Track and enforce coverage thresholds
  • Multiple Formats: Output as default, JSON, JUnit, or GitHub Actions format
  • Fail Fast: Stop on first failure or continue to see all results

All Test Configuration Properties

PropertyTypeDefaultDescription
Global Options (test: top-level)
parallelbooleanfalseRun tests across services in parallel
failFastbooleanfalseStop immediately on first test failure
coveragebooleanfalseCollect code coverage for all services
outputDirstring.test-resultsDirectory for test output files
outputFormatenumdefaultOutput format: default, json, junit, github-actions
Service-Level Options (services.NAME.test)
unitobject-Unit test configuration (see Test Type Properties)
integrationobject-Integration test configuration (see Test Type Properties)
e2eobject-End-to-end test configuration (see Test Type Properties)

Test Type Properties (unit/integration/e2e)

PropertyTypeDefaultDescription
commandstringauto-detectTest command to run (e.g., "npm test", "pytest")
pathstring-Path to test directory or file
coveragebooleaninheritOverride coverage collection for this test type
coverageThresholdnumber-Minimum coverage percentage (0-100, fails if below)
timeoutstring5mTest timeout (e.g., "30s", "5m", "1h")
envobject-Environment variables for tests (key-value pairs)

Output Format Options

FormatUse CaseDescription
defaultDevelopmentHuman-readable console output with colors
jsonAutomationMachine-readable JSON for scripts and tools
junitCI/CDJUnit XML for CI systems (Jenkins, Azure DevOps)
github-actionsGitHub CIGitHub Actions annotations and summaries

🏗️infra (Infrastructure Configuration)

Configure how Azure infrastructure is provisioned for your application. Supports Bicep and Terraform!

infra:
provider: bicep # or 'terraform'
path: ./infra # Default: infra
module: main # Default: main
# Terraform example
infra:
provider: terraform
path: ./infrastructure
module: main

Infrastructure Properties

  • provider - bicep or terraform (default: bicep)
  • path - Relative path to infrastructure templates (default: infra)
  • module - Default provisioning module name (default: main)

🔄pipeline (CI/CD Configuration)

Configure continuous integration pipeline settings for GitHub Actions or Azure DevOps.

pipeline:
provider: github # or 'azdo' for Azure DevOps
# Variables from azd environment to pass to pipeline
variables:
- AZURE_ENV_NAME
- AZURE_LOCATION
# Secrets from azd environment to pass to pipeline
secrets:
- AZURE_SUBSCRIPTION_ID
- DATABASE_PASSWORD

Pipeline Properties

  • provider - github or azdo (default: github)
  • variables - Environment variables to set as pipeline variables
  • secrets - Environment variables to set as pipeline secrets

🚀Deployment & Cloud Properties

Resource Group

Override the default resource group name used for infrastructure provisioning:

resourceGroup: my-custom-rg-name # Supports environment variable substitution

Required Versions

Specify version constraints for azd CLI and extensions:

requiredVersions:
azd: ">= 0.6.0-beta.3"
extensions:
azure-app: ">=1.0.0"
my-extension: "~2.0.0" # Supports semver constraints

Infrastructure Configuration (infra)

Define infrastructure provider and location:

infra:
provider: bicep # or terraform
path: infra # Path to infrastructure code (default: infra)
module: main # Main module name (bicep) or path (terraform)
PropertyTypeDefaultDescription
providerenumbicepInfrastructure as code provider: bicep, terraform
pathstringinfraRelative path to infrastructure code directory
modulestringmainMain module name (Bicep) or relative path (Terraform)

Pipeline Configuration (pipeline)

Configure CI/CD pipeline settings:

pipeline:
provider: github # or azdo (Azure DevOps)
variables:
NODE_ENV: production
secrets:
- API_KEY
- DATABASE_URL
PropertyTypeDescription
providerenumCI/CD provider: github, azdo (Azure DevOps)
variablesobjectKey-value pairs for pipeline variables
secretsarrayNames of secrets to configure in pipeline

State Management (state)

Configure remote state storage for infrastructure state (Terraform, etc.):

state:
remote:
backend: AzureBlobStorage
config:
accountName: mystorageaccount
containerName: tfstate # Optional, defaults to project name
endpoint: blob.core.windows.net # Optional
PropertyTypeDescription
remote.backendenumRemote state backend: AzureBlobStorage
remote.config.accountNamestringAzure Storage account name
remote.config.containerNamestringBlob container for state (default: project name)
remote.config.endpointstringStorage endpoint (default: blob.core.windows.net)

Platform Configuration (platform)

Integration with Azure Dev Center for enterprise scenarios:

platform:
type: devcenter
config:
name: my-dev-center
project: my-dev-center-project
catalog: my-catalog
environmentDefinition: my-env-def
environmentType: dev
PropertyTypeDescription
typeenumPlatform type: devcenter
config.namestringAzure Dev Center name
config.projectstringDev Center project name
config.catalogstringCatalog name for environment definitions
config.environmentDefinitionstringEnvironment definition name
config.environmentTypestringEnvironment type (dev, test, prod)

Workflows (workflows)

Customize azd command workflows (e.g., change the order of provision, package, deploy):

workflows:
up:
steps:
- azd: package --all
- azd: provision
- azd: deploy --all
# Or as array shorthand:
# workflows:
# up:
# - azd: package --all
# - azd: provision
# - azd: deploy --all
PropertyTypeDescription
{workflow-name}object/arrayWorkflow steps for custom command (up, provision, deploy, etc.)
stepsarrayArray of workflow steps (object format)
steps[].azdstringazd command to run (e.g., "provision", "deploy --all")

Available Workflow Commands

Commands that can be customized with workflows:

upprovisiondeploydownpackagerestore

Cloud Configuration (cloud)

Deploy to sovereign clouds (Azure Government, Azure China, etc.):

cloud:
name: AzureUSGovernment # AzureCloud (default), AzureChinaCloud, AzureUSGovernment
PropertyTypeValuesDescription
nameenumAzureCloud, AzureChinaCloud, AzureUSGovernmentAzure cloud environment (default: AzureCloud)

Service Deployment Properties

Additional service properties for Azure deployment:

services:
api:
host: containerapp # Required: appservice, containerapp, function, springapp, staticwebapp, aks, ai.endpoint
project: ./api
# Deployment configuration
resourceGroup: custom-rg # Override default resource group
resourceName: my-api-instance # Override resource name discovery
module: api-module # Infrastructure module for this service
dist: ./dist # Path to deployment artifacts
# API version for deployment
apiVersion: "2023-05-01" # Container App API version
# AKS-specific configuration
k8s:
deploymentPath: manifests # Path to k8s manifests
namespace: production # K8s namespace
deployment:
name: api-deployment
service:
name: api-service
ingress:
name: api-ingress
relativePath: /api
# Service hooks (in addition to global hooks)
hooks:
predeploy:
run: npm run build
shell: sh
postdeploy:
run: echo "Deployed successfully!"
shell: sh
prerestore:
run: npm install
postrestore:
run: echo "Restored dependencies"
prebuild:
run: npm run lint
postbuild:
run: echo "Build complete"
prepackage:
run: npm run test
postpackage:
run: echo "Package ready"

Service Host Types

  • appservice - Azure App Service (requires project + runtime)
  • containerapp - Azure Container Apps (requires image OR project)
  • function - Azure Functions (requires project)
  • springapp - Azure Spring Apps (requires project)
  • staticwebapp - Azure Static Web Apps (requires project)
  • aks - Azure Kubernetes Service (requires project + k8s config)
  • ai.endpoint - Azure AI Studio endpoints (requires project + config)
  • azure.ai.agent - Azure AI Agents (requires project)

Kubernetes (k8s) Configuration

For AKS deployments, configure Kubernetes manifest paths and resource names:

PropertyTypeDescription
deploymentPathstringPath to Kubernetes manifest files (relative to service project)
namespacestringKubernetes namespace for deployment (default: default)
deployment.namestringDeployment resource name
service.namestringService resource name
ingress.namestringIngress resource name
ingress.relativePathstringURL path for this service (e.g., /api, /admin)

Resource Types

Azure resource types with special configuration options:

resources:
# Storage Account
storage:
type: storage
containers: # Optional: containers to create
- uploads
- backups
# Cosmos DB
cosmosdb:
type: db.cosmos
containers:
- name: users
partitionKeys: ["/id"]
- name: orders
partitionKeys: ["/customerId", "/region"]
# Event Hubs
eventhubs:
type: messaging.eventhubs
hubs: # Hubs to create
- telemetry
- logs
# Service Bus
servicebus:
type: messaging.servicebus
queues:
- orders
- notifications
topics:
- events
# App Service host resource
webapp:
type: host.appservice
port: 80
runtime:
stack: node
version: "20-lts"
startupCommand: "npm start"
env:
- name: NODE_ENV
value: production
# Container App host resource
api-host:
type: host.containerapp
port: 8080
env:
- name: LOG_LEVEL
value: info
- name: DB_PASSWORD
secret: DB_PASSWORD_SECRET
# AI/ML Resources
openai:
type: ai.openai.model
model:
name: gpt-4
version: "0613"
ai-project:
type: ai.project
models:
- name: gpt-4o
version: "2024-05-13"
format: OpenAI
sku:
name: GlobalStandard
usageName: OpenAI.GlobalStandard.gpt-4o
capacity: 10
search:
type: ai.search
# Database resources
postgres:
type: db.postgres
mysql:
type: db.mysql
redis:
type: db.redis
mongodb:
type: db.mongo
# Key Vault
vault:
type: keyvault

🎪The Grand Finale: Complete Example

Feast your eyes on this masterpiece! A real-world azure.yamlwith all the bells and whistles. This is what peak performance looks like! 🏆

name: epic-fullstack-app
# 🎯 Global test configuration
test:
parallel: true
coverage:
enabled: true
threshold: 80
# 📋 Prerequisites
reqs:
- name: node
minVersion: "20.0.0"
- name: docker
checkRunning: true
- name: python
minVersion: "3.11"
# 🪝 Lifecycle hooks
hooks:
prerun:
run: echo "🚀 Starting up..."
shell: sh
postrun:
run: echo "✨ Ready to code!"
shell: sh
prestop:
run: echo "⏹️ Shutting down..."
shell: sh
continueOnError: true
poststop:
run: echo "🧹 Cleanup complete!"
shell: sh
# 📊 Global logging
logs:
filters:
exclude:
- "npm warn"
- "Debugger listening"
classifications:
- text: "error"
level: error
- text: "warning"
level: warning
analytics:
pollingInterval: "10s"
defaultTimespan: "30m"
# 🎭 Services
services:
# Next.js frontend
web:
language: TypeScript
project: ./frontend
ports: ["3000"]
environment:
- name: NEXT_PUBLIC_API_URL
value: http://localhost:8000
- name: NEXT_PUBLIC_ANALYTICS_ID
secret: ANALYTICS_SECRET
uses:
- api
healthcheck:
path: /api/health
interval: 10s
test:
unit:
command: npm test
coverage:
threshold: 85
# FastAPI backend
api:
language: Python
project: ./backend
entrypoint: main.py
ports: ["8000"]
environment:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/app
REDIS_URL: redis://localhost:6379
uses:
- postgres
- redis
healthcheck:
path: /health
interval: 15s
timeout: 5s
retries: 3
start_period: 30s
logs:
analytics:
tables:
- ContainerAppConsoleLogs_CL
test:
unit:
command: pytest tests/
path: tests
integration:
command: pytest tests/integration/
# Background worker
worker:
language: Python
project: ./worker
type: process
environment:
QUEUE_URL: redis://localhost:6379
uses:
- redis
healthcheck:
type: process
interval: 30s
# TypeScript build watcher
build-types:
project: ./shared
command: tsc --watch --preserveWatchOutput
mode: watch
healthcheck:
type: output
pattern: "Found 0 errors"
timeout: 60s
# PostgreSQL database
postgres:
image: postgres:16
ports: ["5432"]
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: app
healthcheck:
type: tcp
interval: 10s
retries: 5
# Redis cache
redis:
image: redis:7-alpine
ports: ["6379"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
# Azurite for Azure Storage emulation
azurite:
image: mcr.microsoft.com/azure-storage/azurite
ports:
- "10000:10000" # Blob
- "10001:10001" # Queue
- "10002:10002" # Table
# ☁️ Azure Resources
resources:
storage:
type: Microsoft.Storage/storageAccounts
keyvault:
type: Microsoft.KeyVault/vaults
appinsights:
type: Microsoft.Insights/components

🎉What's Happening Here?

  • 🎯 Next.js frontend with environment variables and tests
  • 🐍 FastAPI backend with health checks and Log Analytics
  • ⚙️ Python background worker for queue processing
  • 👀 TypeScript compiler in watch mode with output monitoring
  • 🐘 PostgreSQL database container with health checks
  • ⚡ Redis cache for sessions and caching
  • ☁️ Azurite for Azure Storage emulation
  • ✅ Prerequisites checking for Node, Docker, and Python
  • 🪝 Lifecycle hooks for setup and notifications
  • 📊 Global logging with filters and Azure Analytics
  • 🧪 Comprehensive testing with coverage tracking

Quick Reference

Cheat sheet for the impatient (we don't judge!):

# Property Quick Reference
## Root Properties (All)
### Required
- name - Application name (required)
### Development (azd app)
- services - Service definitions
- reqs - Prerequisites
- hooks - Lifecycle hooks (prerun, postrun, prestop, poststop)
- logs - Logging configuration
- test - Testing configuration
### Deployment (azd)
- resources - Azure resources
- infra - Infrastructure config (Bicep/Terraform)
- pipeline - CI/CD configuration
- resourceGroup - Override resource group
- requiredVersions - Version constraints
- state - Remote state management
- platform - Dev Center integration
- workflows - Custom command workflows
- cloud - Sovereign cloud selection
- metadata - Custom metadata
## Service Properties
### Core (azd app)
- language - Programming language
- project - Project directory
- entrypoint - Entry file
- command - Run command override
- type - http|tcp|process|container
- mode - daemon|watch|build|task
### Network & Containers
- ports - Port mappings
- image - Docker image
- docker - Build configuration
- environment - Env variables
### Dependencies & Health
- uses - Service/resource dependencies
- healthcheck - Health monitoring
### Configuration (azd app)
- logs - Service logging config
- test - Service test config
### Deployment (azd)
- host - Azure service type (required for deployment)
- resourceGroup - Service resource group
- resourceName - Override resource name
- apiVersion - API version
- module - Infrastructure module
- dist - Deployment artifacts path
- k8s - Kubernetes configuration
- config - Host-specific config
- hooks - Service lifecycle hooks
## Resource Properties
- type - Resource type (required)
- uses - Dependencies
- existing - Is existing resource
- [type-specific] - Container arrays, SKU config, etc.

💎Pro Tips & Tricks

🎯 Let Auto-Detection Do Its Thing

Start minimal! azd app will figure out your language, framework, and run commands. Add overrides only when needed.

🔗 Use Dependencies Wisely

The uses property ensures services start in the right order. Your API won't start until the database is healthy!

🏥 Health Checks Are Your Friend

Proper health checks prevent race conditions. For watch mode services, use output patterns instead of HTTP checks!

📊 Filter Those Logs

Nobody needs to see "npm warn deprecated" 500 times. Use log filters to keep your output clean and focused!

🐳 Containers for Infrastructure

Run databases, caches, and Azure emulators as containers. No need to install PostgreSQL on every dev machine!

🧪 Test Early, Test Often

Configure tests in azure.yaml so everyone runs them the same way. Enforce coverage thresholds to maintain quality!

🏷️metadata (Custom Metadata)

Store custom metadata about your application. Commonly used to track template information.

metadata:
template: todo-nodejs-mongo@0.0.1-beta
author: Azure Samples
description: Full-stack application with Node.js and MongoDB
customField: any-value-you-want

The metadata section accepts any custom properties you want to store (additionalProperties: true). Most commonly used to track which template a project was created from.

Metadata Properties

PropertyTypeDescription
templatestringTemplate identifier (common convention: name@version)
authorstringTemplate or project author
descriptionstringTemplate or project description
{custom}anyAny custom fields (no restrictions)

🔍Schema Validation & IntelliSense

Get autocomplete and validation in VS Code by adding this to the top of your azure.yaml:

Schema v1.1 (Local Development + Deployment)

Use v1.1 if you're using azd app for local development. This is a superset that includes all v1.0 properties plus local development features:

# yaml-language-server: $schema=https://raw.githubusercontent.com/jongio/azd-app/main/schemas/v1.1/azure.yaml.json
name: my-app
services:
api:
project: ./api
ports: ["8080"] # v1.1 feature
healthcheck: # v1.1 feature
path: /health

Schema v1.0 (Deployment Only)

Use v1.0 if you're only using standard azd for Azure deployment without local development features:

# yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json
name: my-app
services:
api:
host: containerapp # v1.0 deployment
project: ./api

💡Which Schema Should I Use?

  • v1.1 - If you use azd app run for local development
  • v1.0 - If you only use azd up/deploy for Azure deployment
  • v1.1 is backward compatible - All v1.0 files work with v1.1 schema

Ready to Build Something Amazing? 🚀

Now that you're an azure.yaml expert, go forth and orchestrate some awesome local development environments!

Get Started Now →