When you read Azure’s documentation on hub-and-spoke architecture with Virtual WAN, it looks straightforward. Deploy a Virtual Hub. Add a firewall. Connect some spokes. Ship it.
Then you hit production, and you discover the truth: Azure resources have opinions about deployment order, runtime state dependencies, and race conditions that no documentation fully captures.
After building enterprise hub infrastructure spanning 4 environments, 6 spoke networks, and managing everything from ExpressRoute circuits to SD-WAN appliances, I learned that successful IaC isn’t about writing templates—it’s about understanding why certain patterns exist and when they matter.
The Knowledge Gap #
Azure’s documentation tells you what resources do. It doesn’t tell you:
- BGP connections fail if deployed in parallel
- DNAT rules need the firewall’s runtime-assigned IP (circular dependency)
- Routing Intent must wait for all gateways or deployments conflict
- DNS zones have shared backend state that serializes updates
- Subnet array order creates implicit dependencies throughout your templates
- Key Vault IP rules churn breaks Application Gateway certificate retrieval
These lessons come from production deployments, failed pipelines, and debugging sessions that start with “Why is this happening?”
The 13-Pattern Series #
This series captures operational knowledge that prevents failure modes before they happen.
Core Deployment Patterns #
1. The @batchSize(1) Pattern: When Parallel is Your Enemy Why BGP connections and DNS zones must deploy sequentially, and how parallel deployment causes “AnotherOperationInProgress” errors that are impossible to debug.
2. Breaking Circular Dependencies: The DNAT Two-Phase Pattern How to deploy firewall DNAT rules that require runtime-assigned public IPs using multi-phase deployments and output passing.
3. Gateway Orchestration: Why Order Matters in Virtual Hub The critical sequence for deploying S2S VPN, P2S VPN, ExpressRoute Gateway, and Routing Intent without Virtual Hub state conflicts.
Advanced Architecture Patterns #
4. The Wrapper Pattern: Taming Azure Verified Modules Building stable platform interfaces over AVM using the Adapter pattern—handling SKU differences, runtime lookups, and module evolution.
5. Cost Optimization Through Ternary Logic Environment-aware configuration that saved $10K annually by adjusting firewall IPs based on dev vs. prod deployments.
6. The Array Index Trap: Documenting Implicit Dependencies Why subnet order matters, how array indexing creates coupling, and patterns to prevent breakage when refactoring.
Production Safety Patterns #
7. Cross-Subscription References with existing Keyword
Referencing and updating resources across Azure subscriptions in hub-and-spoke architectures.
8. Dynamic Multi-Tenant Configuration with Filter Functions
Using Bicep’s filter() for automatic domain-to-WAF-policy association in Azure Front Door multi-workload scenarios.
9. Conditional Locking for Environment-Specific Protection Production resource locks that activate based on deployment context, not separate parameter files.
Operational Patterns #
10. Avoiding Key Vault Dependency Hell Service endpoint patterns that eliminate public IP churn and prevent Application Gateway deployment failures.
11. Secure Parameter Injection with Environment Variables
Using readEnvironmentVariable() for secrets and multi-environment deployments from a single parameter file.
12. DNS Fallback: Handling Empty Outputs Gracefully Ternary conditionals that make deployments resilient to partial failures during retries.
13. Deployment Scopes: Multi-Subscription, Multi-Environment Configuration Centralizing environment-specific settings (subscription IDs, IP ranges) while keeping parameters DRY.
Who This Series Is For #
This is for engineers who:
- Have hit walls that Azure documentation doesn’t address
- Need to scale infrastructure beyond quickstart examples
- Want to understand why patterns exist, not just copy-paste code
- Debug production IaC failures and need root cause understanding
- Build platforms that other teams depend on
This is NOT for:
- Azure beginners (start with Microsoft Learn first)
- Single-environment hobby projects
- Anyone looking for quickstart templates
The Infrastructure Context #
These patterns emerged from managing:
- 6 spoke networks across business units
- 4 environments (dev, prod, disaster recovery)
- Hub-and-spoke with Azure Virtual WAN, Firewall Premium, ExpressRoute, dual VPN gateways
- 1,258 Bicep files of templates, parameters, and automation
- Multi-subscription governance and cost optimization
- Multi-region disaster recovery architecture
What Makes This Different #
Most Azure IaC content shows you the happy path. This series shows you:
- What breaks and why
- Failed approaches I tried first
- Design decisions and trade-offs
- Production constraints that force certain patterns
- Code references to actual implementation (line numbers, modules, parameter files)
Every pattern is battle-tested in production.
Technologies Covered #
- Azure Virtual WAN, Virtual Hub
- Azure Firewall Premium
- ExpressRoute, Site-to-Site VPN, Point-to-Site VPN
- Azure Front Door, Application Gateway
- Private DNS Resolver, DNS zones
- Key Vault, domain controllers
- Bicep (advanced features: @batchSize, existing resources, filter functions, ternary operators)
- Azure Verified Modules (AVM)
- Multi-subscription, multi-region architecture
Start Reading #
I recommend reading in order if you’re building hub-and-spoke infrastructure. If you’re debugging a specific issue, jump to the relevant pattern.
Start with: The @batchSize(1) Pattern — it’s the most common gotcha that affects BGP, DNS, and any shared-state resources.
This series represents knowledge gained from 6 months building and operating enterprise Azure infrastructure at scale. All code examples reference actual production templates.
Skills Demonstrated: Infrastructure as Code, Azure networking, Deployment orchestration, Problem-solving under constraints, Production operations, Platform engineering