ADR-0004: Deployment Ordering
Status: Accepted | Date: 2026-02-02
Context
Section titled “Context”In the full scenario (Firewall + VPN Gateway), intermittent deployment failures occurred with InternalServerError on the Azure Firewall. The first attempt failed but retry succeeded.
Root Cause
Section titled “Root Cause”A race condition when deploying Azure Firewall and VPN Gateway simultaneously:
- Both modules depend on the hub VNet (
networkingHub) - Both modify the hub VNet (Firewall attaches to
AzureFirewallSubnet, VPN Gateway toGatewaySubnet) - Azure Resource Manager attempts concurrent VNet updates
- Result:
InternalServerErrorwhen the VNet is locked by one operation
Decision
Section titled “Decision”Serialize Firewall and VPN Gateway deployments using explicit dependsOn.
When both deployFirewall and deployVpnGateway are true (full scenario), the VPN Gateway module waits for the Firewall module to complete:
module vpnGateway 'modules/vpn-gateway.bicep' = if (deployVpnGateway) { dependsOn: deployFirewall ? [firewall] : [] // ...}This adds ~10–15 minutes to the full scenario deployment time but eliminates first-attempt failures.
Consequences
Section titled “Consequences”Positive: 100% first-attempt success rate for the full scenario, no more manual retries needed.
Negative: full scenario takes 40–55 minutes instead of 25–35 minutes. Acceptable trade-off for SMB deployments that run once per customer.