The Azure Developer CLI, commonly called azd, provides a developer-focused way to provision Azure resources, deploy applications, and manage environment configuration from the command line.
Standard azd commands cover many common workflows, but real projects often have organization-specific deployment requirements. A team might need a custom command that validates infrastructure, runs a migration, checks configuration, or performs a deployment step that is specific to its application.
Azure Developer CLI supports extensions that allow developers to add custom functionality without changing the core azd command.
For .NET teams, this can be useful when a deployment workflow needs to combine Azure provisioning with application-specific tasks.
What Are Azure Developer CLI Extensions?
An azd extension adds additional functionality to the Azure Developer CLI.
The standard CLI might provide commands such as:
azd init
azd provision
azd deploy
azd up
An extension can add a custom command that fits the team's workflow.
For example:
azd myteam validate
or:
azd myteam migrate
The exact command structure depends on how the extension is implemented.
The important idea is that developers can package repeatable Azure development and deployment operations behind a CLI command rather than asking every developer to remember a long sequence of scripts.
Why Build a Custom Deployment Command?
Consider a .NET application that requires several deployment steps:
Provision Azure resources
↓
Build application
↓
Run validation
↓
Deploy .NET application
↓
Run database migration
↓
Verify deployment
Without an extension, developers might execute several independent commands:
azd provision
dotnet test
azd deploy
dotnet ef database update
The problem is that every developer may eventually execute the steps differently.
A custom command can provide a consistent workflow:
azd myteam deploy
The extension can coordinate the required operations and stop when a prerequisite fails.
Extension Architecture
A simple architecture looks like this:
Developer
|
v
azd myteam deploy
|
v
Custom Extension
|
+--> Validate environment
|
+--> Run tests
|
+--> Provision resources
|
+--> Deploy application
|
+--> Verify deployment
The extension becomes an orchestration layer.
It should not duplicate functionality that azd already provides unless there is a clear reason.
Choosing an Extension Implementation
An extension can be implemented using a supported command-line technology such as Go or another executable that integrates with azd's extension model.
For teams building an internal deployment tool around .NET, it is also possible to keep application-specific logic in PowerShell or shell scripts and have the extension invoke those tools.
A useful design principle is:
Extension
↓
Orchestrates deployment
↓
Existing Azure / .NET tools
Rather than:
Extension
↓
Reimplements Azure deployment APIs
The first approach generally keeps the custom layer smaller and easier to maintain.
Creating a Simple Custom Command
Suppose an organization wants:
azd company validate
to perform application checks before deployment.
A simple command can execute validation logic and return a non-zero exit code when validation fails.
For example, the underlying .NET validation command could be:
dotnet test --configuration Release
followed by:
dotnet build --configuration Release --no-restore
The extension can orchestrate these operations and report a clear result.
Conceptually:
azd company validate
|
+--> dotnet test
|
+--> dotnet build
|
+--> Configuration validation
|
+--> Return success/failure
The key is to make the command deterministic. If a developer runs the command twice against the same environment, it should not unexpectedly create different infrastructure or modify unrelated resources.
Passing Environment Information
One of the most useful capabilities of azd is environment management.
Deployment commands often need values such as:
AZURE_SUBSCRIPTION_ID
AZURE_LOCATION
AZURE_RESOURCE_GROUP
A custom extension should avoid hardcoding these values.
Instead, it should obtain configuration from the active azd environment or explicit command arguments.
For example, a deployment command might accept:
azd company deploy --environment production
The extension can then use the environment configuration rather than embedding production-specific values in source code.
This makes the same command usable across development, testing, and production environments.
Example .NET Deployment Validation
Suppose an ASP.NET Core application requires a database connection string.
A custom deployment command can validate that the required configuration exists before provisioning or deploying.
A simple .NET validation method could be:
public static void ValidateConfiguration(
IConfiguration configuration)
{
var connectionString =
configuration.GetConnectionString("Default");
if (string.IsNullOrWhiteSpace(connectionString))
{
throw new InvalidOperationException(
"Database connection string is missing.");
}
}
The deployment command can execute this validation before continuing.
This is useful because failing early is usually preferable to discovering a missing configuration value after the application has been deployed.
Adding a Deployment Verification Step
Deployment success does not necessarily mean application success.
For example:
Azure deployment succeeded
↓
Container started
↓
Application failed during startup
A custom command can include a verification step.
For an ASP.NET Core service exposing a health endpoint:
curl --fail \
https://api.example.com/health
If the health endpoint fails, the command should return a failure status.
The overall workflow becomes:
Deploy
↓
Wait for application
↓
Health check
↓
Success / Failure
The exact readiness period should be configurable rather than relying on an arbitrary fixed delay.
Handling Failures Correctly
A deployment extension should fail fast when a critical operation fails.
For example:
Validation
|
+-- Failed → Stop
|
v
Provision
|
+-- Failed → Stop
|
v
Deploy
|
+-- Failed → Stop
|
v
Verify
Avoid workflows where the extension continues after a critical failure.
A command such as:
azd company deploy
should provide enough information for the developer to understand which step failed.
Logging and Exit Codes
Command-line tools need predictable exit behavior.
A successful operation should return exit code 0.
A failure should return a non-zero exit code.
For example:
Validation failed
Exit code: 1
This becomes particularly important when the custom command is called from CI/CD.
A pipeline can then use:
azd company deploy
and stop automatically when the command returns a failure.
Logs should distinguish between:
INFO
WARNING
ERROR
and should avoid printing sensitive values such as passwords, access tokens, and connection strings.
Security Considerations
Custom deployment commands often have access to powerful Azure credentials.
That makes security an important part of extension design.
Avoid Hardcoded Secrets
Never put secrets directly in source code:
var password = "MyProductionPassword";
Instead, retrieve secrets through the application's approved secret-management mechanism.
Avoid Logging Credentials
Do not print:
ConnectionString=Server=...;Password=...
to deployment logs.
Logs frequently become accessible to more people and systems than the original deployment environment.
Validate Inputs
If the command accepts a resource group or environment name, validate the input before using it in shell commands.
Avoid constructing commands from untrusted input.
For example, prefer process APIs that pass arguments separately instead of building a shell command string.
Common Mistakes
Rebuilding Existing azd Functionality
If azd deploy already performs the required deployment, a custom extension should add value rather than simply wrapping the same command with another name.
Hardcoding Environment Names
Avoid code such as:
production-resource-group
inside the extension.
Environment configuration should remain external.
Ignoring Exit Codes
A command that prints an error but still returns success can cause CI/CD pipelines to report false positives.
Making the Extension Too Large
An extension should ideally remain focused on orchestration and organization-specific workflow.
Large amounts of business logic can make the deployment tool difficult to maintain.
Skipping Post-Deployment Verification
Infrastructure provisioning can succeed while the application remains unhealthy.
Always consider an appropriate verification step.
Troubleshooting Custom Commands
Start by confirming that the extension is installed and recognized by the Azure Developer CLI.
Then verify the command being executed:
azd --help
Check the extension's own help output:
azd company --help
Run the command with any supported diagnostic or verbose logging options to identify where execution fails.
For deployment problems, separate the investigation into:
Extension problem
↓
Command execution problem
↓
Azure authentication problem
↓
Infrastructure problem
↓
Application deployment problem
↓
Application runtime problem
This prevents application failures from being incorrectly diagnosed as CLI failures.
Best Practices
Keep custom commands focused on a clear developer workflow.
Reuse existing azd, Azure, and .NET tooling where possible.
Keep environment configuration outside the extension's source code.
Never hardcode secrets.
Use meaningful exit codes.
Fail fast on critical deployment errors.
Add health or verification checks after deployment.
Make commands safe to run from CI/CD.
Keep logs useful without exposing sensitive information.
Test extensions against development environments before using them for production deployments.
Advantages and Disadvantages
Advantages
Creates consistent organization-specific deployment workflows.
Reduces repetitive manual commands.
Can combine Azure and .NET tooling into one workflow.
Works well with CI/CD automation.
Provides a single developer-facing command.
Can add organization-specific validation and verification.
Disadvantages
Adds another tool that must be maintained.
Extension compatibility can become a concern as CLI behavior evolves.
Poorly designed commands can hide important deployment details.
Incorrect error handling can create false deployment success.
Extensions with excessive responsibilities can become difficult to test and maintain.
Conclusion
Azure Developer CLI extensions provide a practical way to customize azd for organization-specific development and deployment workflows.
For a .NET team, a custom command can combine validation, Azure provisioning, application deployment, database operations, and post-deployment verification into a consistent workflow.
The strongest design keeps the extension focused:
azd Custom Command
↓
Validate
↓
Provision
↓
Deploy
↓
Verify
The extension should orchestrate existing tools rather than unnecessarily replacing them. It should also treat authentication, secrets, exit codes, logging, and environment configuration as first-class concerns.
When these principles are followed, custom azd commands can make complex Azure deployment workflows easier to repeat, automate, and maintain without forcing every developer to learn a long sequence of project-specific commands.