Every landing zone deployment I've reviewed in the past year has told the same story: the hub works beautifully, the networking is sound, the governance policies are in place — and the hub's monthly bill is meaningfully higher than it needs to be. Not because anyone made a mistake, but because the standard landing zone pattern defaults toward Premium SKUs, larger VPN gateways, and comprehensive monitoring, as if every enterprise needs enterprise-maximum from day one.

Here's what I keep seeing in practice: a firewall running well under its throughput ceiling on Premium. A VPN gateway sized for 1 Gbps of aggregate traffic while the office link carries a couple of hundred megabits. A Log Analytics workspace ingesting tens of gigabytes a day, much of it diagnostics nobody has queried in six months.

None of this is negligence. The Cloud Adoption Framework's defaults are designed to be safe, and "safe" is the right default when you don't know the workload yet. The problem starts when teams deploy the defaults and then never revisit them.

I've been working with Malaysian enterprises on Azure landing zones since the Malaysia West region launched, and cost optimization is the conversation that keeps coming up — usually with the wrong starting point. Most teams hear "cost optimization" as "turn things off." It isn't. It means right-sizing what you have: deliberate SKU choices based on measured workload patterns.

Let me walk through the playbook I use, grounded in verified Azure documentation and current Malaysia West pricing, with the CLI commands and IaC templates you can take back to your team.

The Over-Provisioning Problem: Why It Happens

Four patterns show up in almost every landing zone review I do in Kuala Lumpur and across Southeast Asia:

1. The "Premium for Safety" firewall trap. Teams select Azure Firewall Premium because the most sensitive reference architectures recommend it. Premium is genuinely valuable — it adds fully managed IDPS and outbound TLS inspection. But if your inspection requirement is L3–L7 filtering, threat-intelligence-based alerting, and web categories, Standard delivers that with autoscaling up to 30 Gbps. Premium scales to 100 Gbps, which is far more than most mid-size hubs will ever push.

2. VPN gateway over-sizing. A typical Malaysian enterprise office — SaaS applications, occasional file transfers, remote-worker VPN — rarely sustains more than 200–300 Mbps across the site link. That is VpnGw1AZ territory (650 Mbps aggregate benchmark). Yet I regularly find VpnGw2AZ or larger deployed "because the template said so."

3. Log Analytics over-ingestion. Diagnostic settings get configured once — all categories enabled, long retention — and nobody revisits them. The workspace quietly grows to tens of gigabytes per day. NSG flow logs, every Application Gateway access log, every Key Vault audit event: all ingested, all billed, mostly unread.

4. Azure Advisor recommendations ignored. Advisor surfaces specific cost recommendations — right-size underutilized VMs, delete unattached disks, purchase reservations. Teams dismiss them as "risky" and keep paying for idle capacity. The governance fear is real, but the answer isn't ignoring the data — it's building a review process around it.

The Landing Zone Cost Playbook

Here's the practical framework I run with clients.

Step 1: Get the Baseline

Before optimizing anything, know what you're actually spending, and where. The Cost Management query REST API — called via az rest, since the az costmanagement CLI extension has no built-in query subcommand — gives you a cost breakdown by resource group:

# Cost breakdown by resource group, month to date (via Cost Management REST API)
az rest --method post \
  --uri "https://management.azure.com/subscriptions/<sub-id>/providers/Microsoft.CostManagement/query?api-version=2023-11-01" \
  --body '{"type":"ActualCost","timeframe":"MonthToDate","dataset":{"granularity":"None","aggregation":{"totalCost":{"name":"Cost","function":"Sum"}},"grouping":[{"type":"Dimension","name":"ResourceGroup"}]}}' \
  --query "properties.rows" -o table

# Current VPN gateway SKU
az network vnet-gateway show \
  --resource-group rg-hub-networking \
  --name vgw-hub-myw \
  --query "sku.name" -o tsv

# Current Azure Firewall SKU tier
az network firewall show \
  --resource-group rg-hub-security \
  --name fw-hub-myw \
  --query "sku.tier" -o tsv

Then measure actual VPN utilization for the last 30 days. VPN gateways expose tunnel and gateway bandwidth metrics in Azure Monitor:

# Gateway S2S Bandwidth (REST metric name: AverageBandwidth), last 30 days
az monitor metrics list \
  --resource "/subscriptions/<sub-id>/resourceGroups/rg-hub-networking/providers/Microsoft.Network/virtualNetworkGateways/vgw-hub-myw" \
  --metric "AverageBandwidth" \
  --aggregation Average \
  --interval P1D \
  --query "value[0].timeseries[0].data[-10:]" \
  -o table

Numbers, not vibes. This is the entire foundation of the exercise.

Step 2: Right-Size Hub Services

Not every hub service needs the same treatment. Here's the decision matrix I use, with verified Malaysia West pay-as-you-go rates (Azure Retail Prices API, listed in USD):

ServiceOver-provisioned defaultRight-sized optionMonthly cost: default → right-sized (USD, Malaysia West PAYG)
Azure FirewallPremium (USD 1.75/hr deployment)Standard (USD 1.25/hr deployment)≈1,278 → ≈913 (deployment only, excludes capacity units and data processed)
VPN GatewayVpnGw2AZ (USD 0.54/hr)VpnGw1AZ (USD 0.21/hr)≈394 → ≈153
Log AnalyticsPAYG ingestion (USD 2.691/GB)100 GB/day commitment tier (USD 229.32/day)Pay-per-GB → ≈6,880/mo flat at 100 GB/day
Azure BastionStandard (USD 0.29/hr first gateway)Basic (USD 0.19/hr)≈212 → ≈139

The firewall decision is where the biggest money is, so let's be precise about the SKUs, because there is a widespread misconception here:

  • Basic is capped at 250 Mbps throughput. It is not a "small enterprise firewall" — it suits small environments only. I would not put it in a production landing zone hub.
  • Standard autoscales up to 30 Gbps and includes threat intelligence, DNS proxy, and web categories. This is the right choice for most mid-size enterprise hubs.
  • Premium adds fully managed IDPS and TLS inspection, scaling to 100 Gbps. Choose it when those security features are genuinely required — typically highly sensitive applications such as payment processing — not as a blanket default.

For a realistic scenario — a 500-user Malaysian enterprise, three branch offices, hybrid connectivity, about 120 concurrent remote users — the hub math looks roughly like this (USD/month, Malaysia West, PAYG, 730 hours):

Over-provisioned hub (Premium-everything defaults):
  Azure Firewall Premium (deployment 1,278 + ~1 avg capacity unit 80):  ~1,358
  VPN Gateway VpnGw2AZ (394) + 3 S2S conns (33) + 120 P2S conns (876):  ~1,303
  Log Analytics PAYG @ 80 GB/day (80 x 2.691 x 30):                      ~6,458
  Azure Bastion Standard (0.29 x 730):                                     ~212
  ------------------------------------------------------------------------
  Total:                                                                 ~9,331

Right-sized hub (measured workload justifies every downgrade):
  Azure Firewall Standard (deployment 913 + ~1 avg capacity unit 51):     ~964
  VPN Gateway VpnGw1AZ (153) + 3 S2S conns (33) + 120 P2S conns (876):  ~1,062
  Log Analytics PAYG after pruning to 40 GB/day (40 x 2.691 x 30):      ~3,229
  Azure Bastion Basic (0.19 x 730):                                        ~139
  ------------------------------------------------------------------------
  Total:                                                                 ~5,394

That's roughly 42% lower — and here's the honest read of those numbers: the single biggest saving is the Log Analytics line, and it comes from pruning ingestion, not from any pricing trick. SKU right-sizing (firewall, gateway, Bastion) contributes roughly a fifth of the total; the rest is deciding you don't need to ingest 40 GB/day of diagnostics nobody queries.

Note that the VPN line barely moves: at 120 concurrent P2S users, the connection charges (USD 0.01/hr each) dominate over the gateway deployment fee. The gateway SKU downgrade is real money (USD 394 → 153), but don't expect it to transform a hub with heavy remote access. Do that math against your measured bandwidth before and after, not before.

At higher ingestion volumes the commitment tier earns its place: above roughly 85 GB/day, PAYG (USD 2.691/GB) costs more per GB than the 100 GB/day commitment tier's effective USD 2.293/GB (USD 229.32/day in Malaysia West). But buying a tier to cover pruned volumes — say committing to 100 GB/day when you're actually ingesting 40 GB/day — means paying for headroom you engineered away. Prune first, commit second.

Step 3: VPN Gateway Right-Sizing — and the 2026 SKU Consolidation You Must Know About

VPN gateway costs are the most misunderstood part of a landing zone, and in 2026 there's a compliance angle too.

Microsoft is consolidating the VPN Gateway SKU portfolio: non-availability-zone SKUs (VpnGw1–VpnGw5) can no longer be created as new gateways since November 1, 2025, and are scheduled for deprecation after September 2026. All new deployments should use the AZ SKUs (VpnGw1AZ–VpnGw5AZ), which are also getting price reductions as part of the consolidation.

The current AZ SKU benchmarks:

SKUGenAggregate throughput benchmarkS2S/VNet tunnelsP2S IKEv2/OpenVPN
VpnGw1AZ1650 Mbps30250
VpnGw2AZ1 / 21 Gbps / 1.25 Gbps30500
VpnGw3AZ1 / 21.25 Gbps / 2.5 Gbps301,000
VpnGw4AZ25 Gbps1005,000
VpnGw5AZ210 Gbps10010,000

If you still have non-AZ gateways in your landing zone, upgrade them now — VpnGw1→VpnGw1AZ and VpnGw2→VpnGw2AZ are supported in-place upgrades, and Microsoft's consolidation guidance says no downtime is expected for gateways that use Standard SKU public IP addresses (if your gateway still carries a Basic SKU public IP, upgrade that to Standard first):

az network vnet-gateway update \
  --resource-group rg-hub-networking \
  --name vgw-hub-myw \
  --sku VpnGw1AZ

For right-sizing between AZ tiers, parameterize the SKU in your IaC so the decision is explicit and reviewable. Terraform:

resource "azurerm_virtual_network_gateway" "hub_vpn" {
  name                = "vgw-hub-myw"
  location            = azurerm_resource_group.hub_networking.location
  resource_group_name = azurerm_resource_group.hub_networking.name

  type     = "Vpn"
  vpn_type = "RouteBased"
  sku      = var.vpn_gw_sku

  ip_configuration {
    name                          = "vpnGwConfig"
    public_ip_address_id          = azurerm_public_ip.vgw_pip.id
    private_ip_address_allocation = "Dynamic"
    subnet_id                     = azurerm_subnet.gateway_subnet.id
  }
}

variable "vpn_gw_sku" {
  description = "VpnGw1AZ: up to 650 Mbps / 30 S2S tunnels. VpnGw2AZ: 1-1.25 Gbps / 500 P2S. Size on measured bandwidth, not template defaults."
  type        = string
  default     = "VpnGw1AZ"
  validation {
    condition     = contains(["VpnGw1AZ", "VpnGw2AZ", "VpnGw3AZ", "VpnGw4AZ", "VpnGw5AZ"], var.vpn_gw_sku)
    error_message = "Only AZ-supported SKUs are allowed (VpnGw1-5 non-AZ SKUs are scheduled for deprecation after September 2026)."
  }
}

One caveat: down-sizing a gateway (say VpnGw2AZ to VpnGw1AZ) isn't always an in-place operation — check the SKU upgrade eligibility matrix first; some transitions require delete/recreate with a maintenance window. Plan it like a change, not a config tweak.

Step 4: Log Analytics Cost Controls

Log Analytics is the silent budget killer in landing zones. Three controls:

# Check current workspace configuration
az monitor log-analytics workspace show \
  --resource-group rg-hub-monitoring \
  --workspace-name law-hub-myw \
  --query "{DailyQuotaGB:dailyQuotaGb, Retention:retentionInDays, Sku:sku.name}" \
  -o table

# Set a daily ingestion quota cap to prevent cost surprises (in GB/day)
az monitor log-analytics workspace update \
  --resource-group rg-hub-monitoring \
  --workspace-name law-hub-myw \
  --quota 100

Then prune what you actually ingest — this is where the real savings are. Audit diagnostic settings on the noisy resources and disable categories nobody queries.

For IaC, the correct way to express a commitment tier is the CapacityReservation SKU with capacityReservationLevel — there is no separate commitment-plan child resource:

resource lawWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
  name: 'law-hub-myw'
  location: resourceGroup().location
  properties: {
    sku: {
      name: 'CapacityReservation'
      capacityReservationLevel: 100 // GB/day commitment tier
    }
    retentionInDays: 90
  }
}

Step 5: Prevent Re-Over-Provisioning with Azure Policy

Right-sizing is wasted if the next deployment over-provisions again. Use Azure Policy to bound SKU choices at the management group level:

targetScope = 'managementGroup'

resource skuPolicy 'Microsoft.Authorization/policyDefinitions@2021-06-01' = {
  name: 'restrict-vpn-gateway-skus'
  properties: {
    displayName: 'Restrict VPN gateway SKUs to right-sized AZ SKUs'
    policyType: 'Custom'
    mode: 'Indexed'
    policyRule: {
      if: {
        allOf: [
          { field: 'type'; equals: 'Microsoft.Network/virtualNetworkGateways' }
          { field: 'Microsoft.Network/virtualNetworkGateways/sku.name'; notIn: allowedSkus }
        ]
      }
      then: { effect: 'deny' }
    }
    parameters: {
      allowedSkus: {
        type: 'Array'
        defaultValue: [ 'VpnGw1AZ' 'VpnGw2AZ' 'VpnGw3AZ' ]
      }
    }
  }
}

The governance mindset flips: instead of enforcing maximum SKUs "for safety," you cap the ceiling and require justification for anything above the reviewed baseline.

Step 6: Build a Monthly Review Cadence

The most important optimization is the simplest: a scheduled review. Here's the script I leave with clients:

#!/bin/bash
# Monthly landing zone cost review — run against your hub subscription
SUBSCRIPTION="<your-hub-subscription-id>"
az account set --subscription "$SUBSCRIPTION"

echo "=== Landing Zone Cost Review — $(date +%Y-%m) ==="

echo "--- Azure Advisor cost recommendations ---"
az advisor recommendation list \
  --category Cost \
  --query "[].{Recommendation:shortDescription.solution, Impact:impact}" \
  -o table

echo "--- Unattached managed disks ---"
az disk list \
  --query "[?managedBy==null].{Name:name, SizeGB:diskSizeGb, Sku:sku.name}" \
  -o table

echo "--- Idle public IPs ---"
az network public-ip list \
  --query "[?ipConfiguration==null].{Name:name, IP:ipAddress, Sku:sku.name}" \
  -o table

Run it monthly. Share the output with finance. Cost awareness built on data, not guesswork, is what survives the next budget cycle.

For teams automating this into a FinOps dashboard, the same query works from Python via the Cost Management REST API:

import requests
from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
token = credential.get_token("https://management.azure.com/.default").token

body = {
    "type": "ActualCost",
    "timeframe": "MonthToDate",
    "dataset": {
        "granularity": "None",
        "aggregation": {"totalCost": {"name": "Cost", "function": "Sum"}},
        "grouping": [{"type": "Dimension", "name": "ResourceGroup"}],
    },
}
r = requests.post(
    "https://management.azure.com"
    "/subscriptions/<sub-id>/providers/Microsoft.CostManagement/query"
    "?api-version=2023-11-01",
    headers={"Authorization": f"Bearer {token}"},
    json=body,
    timeout=30,
)
for row in r.json()["properties"]["rows"]:
    print(f"{row[1]:<40} USD {row[0]:,.2f}")

Pitfalls I Keep Seeing

  • Treating Firewall Basic as an enterprise option. 250 Mbps is its ceiling. For a landing zone hub, the realistic choice is Standard vs. Premium, decided by whether you need IDPS/TLS inspection — not by defaulting to Premium.
  • Deploying non-AZ VPN gateway SKUs in 2026. You can't create new ones, and existing ones are scheduled for deprecation after September 2026. If you inherited them, upgrade to the matching AZ SKU now.
  • Buying Log Analytics commitment tiers before pruning ingestion. The 100 GB/day tier (USD 229.32/day in Malaysia West) only beats PAYG above roughly 85–90 GB/day. Below that, reduce ingestion first; then commit.
  • Session recording surprise on Bastion. Teams downsize expecting to keep session recording — it's a Premium SKU feature. Map compliance needs to the SKU before you save a few hundred ringgit.
  • One-off optimization. SKU choices drift. Without a monthly review cadence and policy guardrails, the hub quietly returns to Premium-everything within two quarters.

Key Takeaways

  1. Landing zone defaults are safe, not optimal. The CAF pattern over-provisions hub services by design; right-sizing is a deliberate review activity. In the worked scenario the hub drops roughly 42% — most of it from pruning Log Analytics ingestion, the rest from SKU choices.
  2. The firewall SKU decision is the biggest SKU lever — but know the real numbers. Basic caps at 250 Mbps, Standard autoscales to 30 Gbps, Premium reaches 100 Gbps with IDPS/TLS inspection. Most mid-size hubs belong on Standard.
  3. VPN gateway consolidation is now a compliance item. Non-AZ VpnGw1–5 SKUs can't be newly created and are scheduled for deprecation after September 2026. Move to VpnGw1AZ–5AZ, and size by measured bandwidth — a typical 200–300 Mbps office link needs VpnGw1AZ (USD 0.21/hr in Malaysia West), not VpnGw2AZ (USD 0.54/hr).
  4. Log Analytics savings come from pruning first, committing second. The 100 GB/day commitment tier beats PAYG only above ~85 GB/day; daily quota caps prevent runaway months either way.
  5. Make it governance, not a project. Azure Policy SKU caps plus a monthly Advisor-and-waste review keep the savings permanent.

Law Wen Feng is a Principal Solution Architect based in Malaysia, specializing in Azure cloud architecture, landing zones, and enterprise infrastructure. Follow his work at wenfeng.my.