The previous lesson ended with two loose ends, one facing inwards and one facing outwards. Inwards: the Barcelona and Palma offices are still outside the Azure network, the legacy check-in system lives on a server in the basement in Barcelona, and Marta Ríos cannot administer the platform from home without exposing something to the internet. Outwards: a customer buying a ticket from South America crosses the Atlantic on every request to West Europe, and they can tell.

Both problems are about connectivity, but in opposite directions. The first is solved with hybrid connectivity: encrypted tunnels or dedicated circuits that join the on-premises network with the Azure virtual network, so that 10.100.0.0/16 and 10.20.0.0/16 behave as a single network. The second is solved with global delivery: services that put the content and the connection termination close to the customer, wherever they are.

This lesson closes module 2 with both, and with a warning that appears on every Azure bill and that almost nobody anticipates: the cost of data transfer out.

Important cost warning: this is the module's most expensive lesson. A VPN gateway is billed by the hour from the moment it is created, even with not a single tunnel connected, and it takes between 20 and 45 minutes to deploy. ExpressRoute involves a contract with a carrier and is not something you test in a lab. Front Door and CDN cost money per data served. Deploy only what you are going to use and delete it the same day.

Contents

  1. Contoso Airlines' hybrid scenario
  2. Point-to-site VPN: administering from home
  3. Site-to-site VPN: connecting Barcelona and Palma
  4. Deploying the gateway with Azure CLI
  5. ExpressRoute: when it justifies its price
  6. Azure Virtual WAN, at a conceptual level
  7. Global delivery: the customer buying from South America
  8. Azure Front Door, Azure CDN and Traffic Manager compared
  9. Public DNS with Azure DNS
  10. The cost of data transfer out
  11. The module's final architecture and cleanup
  12. Common Mistakes and Tips
  13. Exercises
  14. Conclusion

  1. Contoso Airlines' hybrid scenario

What stays on premises after the migration, and why:

System Where it lives Why it is still there What it needs from Azure
Legacy check-in A server in Barcelona Integrated with the accounting system and with a certified card reader Reading the sales from db-reservas every night
Ground staff workstations Barcelona and Palma They are physical workstations Reaching the operations dashboard and the Azure Files share
On-premises directory Barcelona Identity synchronization still pending (module 4) Employee authentication
Marta Ríos's administration A laptop, from home or while travelling She is a person, not a system Reaching snet-gestion and Bastion without opening ports

Remember the addressing plan settled in the previous lesson, because hybrid connectivity is where that plan proves its worth: Barcelona is 10.100.0.0/16, Palma 10.101.0.0/16, the Azure hub 10.10.0.0/16 and production 10.20.0.0/16. Nothing overlaps, so everything can be routed.

The three connectivity options, compared at a glance:

Option Where it travels Bandwidth Latency Cost Time to set up
Point-to-site VPN The internet, encrypted The client's Variable Very low Minutes
Site-to-site VPN The internet, encrypted (IPsec) Up to ~1–10 Gbps depending on SKU Variable, depends on the internet Low Hours
ExpressRoute The carrier's private circuit 50 Mbps – 100 Gbps Predictable, with an SLA High Weeks or months

  1. Point-to-site VPN: administering from home

A point-to-site VPN (P2S) connects one individual machine to the virtual network. Marta Ríos installs a client on her laptop, authenticates, and her laptop receives an address from a dedicated range, with access to the network's private resources.

Its components:

Component What it is
VPN gateway The Azure resource that terminates the tunnels; it lives in GatewaySubnet
Client address pool The range from which IPs are assigned to the laptops; it cannot overlap with anything
Authentication Certificates, Microsoft Entra ID or RADIUS
Protocol OpenVPN (recommended, cross-platform), IKEv2 or SSTP

Contoso reserves 172.16.30.0/24 for the P2S clients: a range that collides neither with Azure (10.x) nor with the offices.

NET_GROUP="rg-contoso-red-pro"
GATEWAY="vgw-contoso-pro"

# Configure point-to-site on an already existing gateway,
# with Microsoft Entra ID authentication and the OpenVPN protocol.
az network vnet-gateway update \
  --resource-group "${NET_GROUP}" \
  --name "${GATEWAY}" \
  --address-prefixes 172.16.30.0/24 \
  --client-protocol OpenVPN \
  --vpn-auth-type AAD \
  --aad-tenant "https://login.microsoftonline.com/<tenant-id>" \
  --aad-audience "<azure-vpn-client-application-id>" \
  --aad-issuer "https://sts.windows.net/<tenant-id>/" \
  --output none

# Download the configuration profile for the client.
az network vnet-gateway vpn-client generate \
  --resource-group "${NET_GROUP}" \
  --name "${GATEWAY}" \
  --authentication-method EAPTLS \
  --output tsv

Authentication with Microsoft Entra ID is preferable to certificates: it integrates with the multi-factor authentication you configured in lesson 01-03, it lets you revoke a person's access by disabling their account, and it does not force you to distribute and renew certificates one by one.

With P2S connected, Marta reaches snet-gestion and Bastion with no public IP exposed at all, which is exactly the promise we left pending in the previous lesson.

  1. Site-to-site VPN: connecting Barcelona and Palma

A site-to-site VPN (S2S) connects an entire network with the virtual network through an IPsec/IKE tunnel between the office's VPN device and the Azure gateway. Nothing is installed on the machines: every workstation in the office reaches Azure transparently.

graph LR
    subgraph BCN["Barcelona office · 10.100.0.0/16"]
        FW1["VPN device<br/>public IP 198.51.100.10"]
        FAC["Legacy check-in"]
    end
    subgraph PMI["Palma office · 10.101.0.0/16"]
        FW2["VPN device<br/>public IP 198.51.100.42"]
    end
    FW1 -->|"IPsec tunnel"| GW["vgw-contoso-pro<br/>GatewaySubnet 10.10.255.0/27"]
    FW2 -->|"IPsec tunnel"| GW
    MAR["Marta Ríos<br/>laptop · P2S 172.16.30.x"] -->|"OpenVPN"| GW
    GW --> HUB["vnet-contoso-hub-pro<br/>10.10.0.0/16"]
    HUB -->|peering with<br/>gateway transit| PRO["vnet-contoso-pro<br/>10.20.0.0/16"]

The four components that have to be created, and in this order:

Component Azure resource What it represents
Gateway subnet GatewaySubnet (/27 or larger) The space where the gateway lives
Public IP ip-vgw-contoso-pro, Standard static The Azure end that the office points at
Virtual network gateway vgw-contoso-pro The tunnel terminator on the Azure side
Local network gateway lng-oficina-barcelona The representation in Azure of the office's network: its public IP and its ranges

The fourth is the one whose name confuses people most: a local network gateway is not a device, but an Azure object that describes the other end. If the office changes its public IP or adds a subnet, this object has to be updated.

Gateway SKUs

SKU Aggregate bandwidth S2S tunnels P2S connections Zone redundancy Use
Basic 100 Mbps 10 128 No Legacy, avoid
VpnGw1 650 Mbps 30 250 No Small production
VpnGw2 1 Gbps 30 500 No Medium production
VpnGw1AZ – VpnGw5AZ 650 Mbps – 10 Gbps 30 500–10,000 Yes Production with a zone requirement

Contoso chooses VpnGw1AZ: the traffic between the offices and Azure is modest (overnight synchronizations and access to a dashboard), but company policy requires zone redundancy on critical components, and the gateway is a single point of failure for both offices.

  1. Deploying the gateway with Azure CLI

#!/usr/bin/env bash
set -euo pipefail

NET_GROUP="rg-contoso-red-pro"
REGION="westeurope"
VNET_HUB="vnet-contoso-hub-pro"
GATEWAY="vgw-contoso-pro"
GW_IP="ip-vgw-contoso-pro"

TAGS=(entorno=produccion proyecto=contoso-reservas centro-coste=CC-1042
      [email protected] criticidad=alta)

# 1. GatewaySubnet in the hub (the name is mandatory and literal).
az network vnet subnet create \
  --resource-group "${NET_GROUP}" --vnet-name "${VNET_HUB}" \
  --name GatewaySubnet --address-prefixes 10.10.255.0/27 --output none

# 2. Standard, zone-redundant public IP.
az network public-ip create \
  --resource-group "${NET_GROUP}" --name "${GW_IP}" \
  --sku Standard --allocation-method Static --zone 1 2 3 \
  --tags "${TAGS[@]}" --output none

# 3. Virtual network gateway. CAREFUL: it takes between 20 and 45 minutes
#    and it starts billing by the hour from the moment it is created.
az network vnet-gateway create \
  --resource-group "${NET_GROUP}" --name "${GATEWAY}" \
  --location "${REGION}" \
  --vnet "${VNET_HUB}" \
  --public-ip-addresses "${GW_IP}" \
  --gateway-type Vpn --vpn-type RouteBased \
  --sku VpnGw1AZ \
  --tags "${TAGS[@]}" \
  --no-wait

# 4. Representation of the Barcelona network (the other end's IP and ranges).
az network local-gateway create \
  --resource-group "${NET_GROUP}" --name lng-oficina-barcelona \
  --gateway-ip-address 198.51.100.10 \
  --local-address-prefixes 10.100.0.0/16 \
  --tags "${TAGS[@]}" --output none

# 5. The same for Palma.
az network local-gateway create \
  --resource-group "${NET_GROUP}" --name lng-oficina-palma \
  --gateway-ip-address 198.51.100.42 \
  --local-address-prefixes 10.101.0.0/16 \
  --tags "${TAGS[@]}" --output none

# 6. IPsec connections (the shared key must come from Key Vault, never from the script).
az network vpn-connection create \
  --resource-group "${NET_GROUP}" --name con-barcelona-pro \
  --vnet-gateway1 "${GATEWAY}" --local-gateway2 lng-oficina-barcelona \
  --shared-key "${BARCELONA_KEY}" --output none

az network vpn-connection create \
  --resource-group "${NET_GROUP}" --name con-palma-pro \
  --vnet-gateway1 "${GATEWAY}" --local-gateway2 lng-oficina-palma \
  --shared-key "${PALMA_KEY}" --output none

Notes on this script, because each one corresponds to a real mistake that is made often:

  • --vpn-type RouteBased: it is the modern type, mandatory for P2S, for multiple tunnels and for most scenarios. PolicyBased is only used with old devices that support nothing else, and it has severe limits.
  • --no-wait: the deployment takes up to 45 minutes. Without this option, your terminal sits blocked.
  • The shared key (--shared-key) is a genuine secret: it must come out of Azure Key Vault (lesson 04-03), never out of a variable written into the repository.
  • The 198.51.100.x addresses come from a range reserved for documentation (RFC 5737): in a real deployment you put the public IPs of the offices' firewalls.
  • The office device has to be configured as well, with the equivalent parameters. Azure generates configuration templates for the most common vendors.

Checking the state of the tunnels:

az network vpn-connection show \
  --resource-group rg-contoso-red-pro --name con-barcelona-pro \
  --query "{Connection:name, Status:connectionStatus, IngressBytes:ingressBytesTransferred, EgressBytes:egressBytesTransferred}" \
  --output table

The status should be Connected. If it shows Connecting indefinitely, 90% of the time it is a mismatch of IPsec parameters between the two ends or a different shared key.

And remember the economic detail from the previous lesson: thanks to --allow-gateway-transit on the hub and --use-remote-gateways on the spokes, this single gateway provides connectivity to vnet-contoso-pro and to vnet-contoso-dev. That is the saving that justifies the hub-and-spoke pattern.

  1. ExpressRoute: when it justifies its price

ExpressRoute is a private connection between your network and Azure through a telecommunications carrier. The traffic never goes over the internet at any point.

Aspect Site-to-site VPN ExpressRoute
Path The public internet, IPsec encrypted The carrier's private circuit
Bandwidth Up to ~10 Gbps (high SKUs), shared with the internet 50 Mbps to 100 Gbps dedicated
Latency Variable: it depends on the state of the internet Predictable and stable
Availability SLA 99.9% (99.95% with active-active) 99.95%, with an end-to-end SLA from the carrier
Encryption IPsec mandatory Not encrypted by default (a private circuit); it can be added
Cost Tens of euros a month plus data transfer out Hundreds or thousands a month, plus the carrier's link
Setup Hours Weeks or months
Access to PaaS services by private IP Requires Private Link Microsoft peering or Private Link

Peering models

Peering What it gives access to Typical use
Private (Azure private peering) Resources with a private IP in your virtual networks The main one: VMs, databases and private endpoints
Microsoft (Microsoft peering) Microsoft's public services (Microsoft 365, PaaS with a public endpoint) Large Microsoft 365 rollouts and access to PaaS without the internet

And two connection models: ExpressRoute Direct (you connect directly to Microsoft's network with 10 or 100 Gbps ports, for enormous volumes) and the usual one through a connectivity provider.

Does Contoso need it?

Marta Ríos evaluates it and decides that no, not yet:

Criterion Contoso's situation Verdict
Data volume Overnight sales synchronization: a few GB The VPN is more than enough
Latency sensitivity Overnight batch processes, not interactive Not critical
Regulatory requirement not to cross the internet There is none: IPsec satisfies the audit Not compelled
Cost Several thousand euros a year, plus the link Not justified

ExpressRoute is justified when any of these applies: regularly moving terabytes, migrating large databases, virtual desktops for hundreds of employees, interactive systems that cannot tolerate latency variability, or a compliance requirement that explicitly forbids crossing the internet. Contoso will reassess if it migrates the whole check-in system. A common pattern, incidentally, is to have ExpressRoute as the primary and a site-to-site VPN as backup, which is cheap and covers a circuit outage.

  1. Azure Virtual WAN, at a conceptual level

When the number of offices and virtual networks grows, building and maintaining gateways, peerings and route tables by hand becomes a full-time job. Azure Virtual WAN is the managed service that automates that work.

Aspect Hand-built hub-and-spoke Azure Virtual WAN
Hub A VNet you create and manage yourself A managed virtual hub provided by Azure
Office connections One by one, with gateways and local objects Automated, with SD-WAN device integration
Routing between spokes Requires an appliance or manual routes Built-in transit between spokes
Multiple regions Global peering and routes by hand Hubs in several regions, interconnected on their own
When it pays off Few networks and few offices Many offices, several regions, VPN + ExpressRoute + P2S at once

For Contoso, with two offices and three virtual networks, the manual hub-and-spoke from lesson 02-05 is simpler and cheaper. Virtual WAN would come into play if the airline grew to twenty branches or if it operated in several regions. It is enough that you know it exists and what problem it solves.

  1. Global delivery: the customer buying from South America

Let us switch direction. A passenger in Buenos Aires goes to www.contosoairlines.example to buy a flight. Everything is in West Europe. Let us see what that costs her.

The round-trip latency between Buenos Aires and Amsterdam is around 220 ms. A typical page load chains several operations in series:

Operation Round trips Approximate time
DNS resolution 1 220 ms (or less with caching)
TCP handshake 1 220 ms
TLS negotiation 1–2 220–440 ms
First HTTP request 1 220 ms
Static resources (images, CSS, JS) Several, in parallel 220 ms minimum per batch

Result: more than a second before anything appears, not counting the server's processing time. And in a ticket-sales funnel, every second of waiting translates into abandonment.

What global delivery fixes, and it is more than people assume:

  1. TLS termination at the edge: the TCP and TLS handshakes happen against a nearby point of presence (São Paulo, for example, about 30 ms away), not against West Europe. Only the already-established request travels to Europe, over persistent connections that are already open and optimized inside Microsoft's network.
  2. Static content caching: images, style sheets and scripts are served from the point of presence, without crossing the Atlantic.
  3. Optimal routing: traffic enters Microsoft's backbone at the closest point and travels over it, not over the public internet.
  4. Failover: if one region's origin does not respond, the global service sends the traffic to another.

  1. Azure Front Door, Azure CDN and Traffic Manager compared

Aspect Azure Front Door Azure CDN Traffic Manager
Layer 7 (HTTP/S) 7 (HTTP/S) DNS
What it does with the traffic Terminates it and forwards it from the edge Serves and caches static content It only answers the DNS query with a destination
TLS termination at the edge Yes Yes No (it never sees the traffic)
Caching Yes Yes, it is its specialty No
Routing by path or header Yes Limited No
WAF Yes (lesson 04-04) Depending on the tier No
Failover Fast, using its own probes — Using probes, but limited by the DNS TTL
Protocols HTTP/S only HTTP/S only Any
Failover speed Seconds — Minutes (it depends on the client's DNS cache)

Selection criteria, in the form of a decision:

  • A website or web API accessible from several regions of the world, that you want to accelerate and protect → Azure Front Door. It is today's default answer, because it includes what used to be done with CDN plus Traffic Manager.
  • Distribution of very large static files only (video, downloads, images) → Azure CDN, if its pricing model works out better for that profile.
  • A service that does not speak HTTP (the legacy engine's protocol, a mail server, a database) or failover between regions without touching the application → Traffic Manager, because it works at the DNS level and is protocol-agnostic.

A warning about Traffic Manager that saves grief: since it only answers DNS queries, failover takes as long as the record takes to expire in the caches of clients and intermediate resolvers. With a 60-second TTL, real failover can take several minutes. It is not the mechanism for failing over in seconds.

Front Door for Contoso Bookings

#!/usr/bin/env bash
set -euo pipefail

GROUP="rg-contoso-reservas-pro"
PROFILE="fd-contoso-global"
ENDPOINT="contoso-reservas"

TAGS=(entorno=produccion proyecto=contoso-reservas centro-coste=CC-1042
      [email protected] criticidad=alta)

# 1. Front Door Standard profile (Premium adds managed WAF and Private Link to the origin).
az afd profile create \
  --resource-group "${GROUP}" --profile-name "${PROFILE}" \
  --sku Standard_AzureFrontDoor --tags "${TAGS[@]}" --output none

# 2. Endpoint: the global name through which traffic enters.
az afd endpoint create \
  --resource-group "${GROUP}" --profile-name "${PROFILE}" \
  --endpoint-name "${ENDPOINT}" --enabled-state Enabled --output none

# 3. Origin group with its health probe and load balancing.
az afd origin-group create \
  --resource-group "${GROUP}" --profile-name "${PROFILE}" \
  --origin-group-name og-reservas \
  --probe-request-type GET --probe-protocol Https \
  --probe-path "/salud" --probe-interval-in-seconds 30 \
  --sample-size 4 --successful-samples-required 3 \
  --additional-latency-in-milliseconds 50 --output none

# 4. Primary origin: the West Europe application.
az afd origin create \
  --resource-group "${GROUP}" --profile-name "${PROFILE}" \
  --origin-group-name og-reservas --origin-name origen-westeurope \
  --host-name app-contoso-reservas-pro.azurewebsites.net \
  --origin-host-header app-contoso-reservas-pro.azurewebsites.net \
  --http-port 80 --https-port 443 --priority 1 --weight 1000 \
  --enabled-state Enabled --output none

# 5. Route with static content caching and redirection to HTTPS.
az afd route create \
  --resource-group "${GROUP}" --profile-name "${PROFILE}" \
  --endpoint-name "${ENDPOINT}" --route-name ruta-principal \
  --origin-group og-reservas --supported-protocols Http Https \
  --patterns-to-match "/*" --forwarding-protocol HttpsOnly \
  --https-redirect Enabled --link-to-default-domain Enabled \
  --enable-caching true --query-string-caching-behavior IgnoreQueryString \
  --output none

echo "Front Door published at: https://$(az afd endpoint show -g "${GROUP}" --profile-name "${PROFILE}" --endpoint-name "${ENDPOINT}" --query hostName -o tsv)"

The options that deserve an explanation:

Option Effect
--probe-path "/salud" Reuses the health endpoint you created in App Service (lesson 02-03)
--sample-size and --successful-samples-required How many probes are evaluated and how many must succeed for the origin to be considered healthy
--additional-latency-in-milliseconds 50 The latency margin within which several origins are considered equally close
--priority 1 The origin's priority: a second origin with priority 2 would be the backup
--https-redirect Enabled Any HTTP request is redirected to HTTPS at the edge
--query-string-caching-behavior Whether the query string forms part of the cache key. Careful: IgnoreQueryString is dangerous on flight search results pages

That last point deserves a serious warning: do not cache personalized responses or availability results. If Front Door caches /vuelos?origen=BCN&destino=EZE ignoring the query string, one customer can see the flights another customer searched for. Contoso caches only /estatico/* (images, CSS, JS) and lets everything dynamic through uncached.

If Contoso later built a second deployment in North Europe, it would be enough to add it as an origin with priority 2, and Front Door would fail over on its own only when the primary's probe failed. Remember, however, the conscious decision from module 1: there is no multi-region active-active setup, on cost grounds.

  1. Public DNS with Azure DNS

Azure DNS hosts your domains' public DNS zones on Microsoft's infrastructure, with global anycast and no servers to maintain. It does not register domains (that is what App Service Domains or your usual registrar are for), it only hosts them.

NET_GROUP="rg-contoso-red-pro"
ZONE="contosoairlines.example"

# 1. Create the public zone.
az network dns zone create -g "${NET_GROUP}" -n "${ZONE}" --output none

# 2. See the name servers that have to be declared at the registrar.
az network dns zone show -g "${NET_GROUP}" -n "${ZONE}" \
  --query nameServers --output tsv

# 3. CNAME record for www pointing at Front Door.
FD_HOST=$(az afd endpoint show -g rg-contoso-reservas-pro \
  --profile-name fd-contoso-global --endpoint-name contoso-reservas \
  --query hostName -o tsv)

az network dns record-set cname set-record \
  -g "${NET_GROUP}" -z "${ZONE}" -n www \
  --cname "${FD_HOST}" --ttl 3600 --output none

# 4. The domain verification record that Front Door requires.
az network dns record-set txt add-record \
  -g "${NET_GROUP}" -z "${ZONE}" -n "_dnsauth.www" \
  --value "<front-door-validation-token>" --output none

# 5. Alias at the zone apex (contosoairlines.example, without www).
#    A CNAME is not allowed at the apex: an Azure alias record is used instead.
az network dns record-set a create \
  -g "${NET_GROUP}" -z "${ZONE}" -n "@" \
  --target-resource "$(az afd endpoint show -g rg-contoso-reservas-pro \
      --profile-name fd-contoso-global --endpoint-name contoso-reservas --query id -o tsv)" \
  --output none

Step 5 solves a classic problem: the DNS standard does not allow a CNAME at the zone apex (the domain without www). Azure DNS's alias records solve it by pointing directly at an Azure resource, and they also update themselves if the resource's IP changes.

About the TTL: a high value (3600 s) reduces queries and cost; a low one (60 s) lets you change destination quickly. Common practice: drop the TTL to 60 seconds a few days before a planned migration and raise it again afterwards.

  1. The cost of data transfer out

Here is the surprise everyone gets with their first Azure bill, and that is why it closes the module's technical content.

Azure's general rule:

  • Data in (ingress) is free. Uploading to Azure costs nothing.
  • Data out (egress) is billed. Everything that leaves for the internet, and a good part of what moves between regions or between zones.
Type of traffic Is it billed?
From the internet into Azure (inbound) No
From Azure to the internet (outbound) Yes, per GB, with the first 100 GB a month free
Between resources in the same region and the same VNet No
Between availability zones in the same region Yes, in some scenarios
Between regions (for example, West Europe → North Europe) Yes
Through a virtual network peering Yes, in both directions
Through a VPN or ExpressRoute Yes (with ExpressRoute it depends on the plan)
Served from the Front Door or CDN cache Yes, at a different and normally lower rate per geographic zone

Where this hurts in Contoso's case:

  1. Boarding passes downloaded by passengers. Every PDF that goes out to the internet is billed. A million downloads of 300 KB is 300 GB a month: small, but real, and it grows with the business.
  2. The overnight synchronization with Barcelona's check-in system over the VPN: it leaves Azure, so it is billed.
  3. GZRS replication of the boarding pass account to North Europe: geo-replication has its own transfer cost.
  4. Traffic between the spokes and the hub over peering: it looks "internal", but it is billed per GB in both directions.

Four ways to reduce it, all applicable right away:

  • Cache at the edge: every response served from the Front Door cache is one less egress from the region (and a faster one).
  • Compress: turning on compression in Front Door and in App Service reduces the bytes served.
  • Do not move data between regions without a reason: process where the data is.
  • Watch the breakdown of the bill: in module 8 you will see how Cost Management breaks spend down by service and by meter type, and how Nuria Peña, the finance lead, reviews it every month with the team. Data transfer out is usually among the top three lines and almost nobody had budgeted for it.

  1. The module's final architecture and cleanup

graph TB
    CLI["Global customers<br/>(Buenos Aires, Madrid, Barcelona…)"] --> DNS["Azure DNS<br/>contosoairlines.example"]
    DNS --> FD["Azure Front Door<br/>fd-contoso-global<br/>TLS at the edge + caching"]
    FD --> WEBAPP["App Service<br/>app-contoso-reservas-pro"]
    WEBAPP --> API["App Service<br/>app-contoso-api-disponibilidad-pro"]
    API --> SQL["db-reservas<br/>(module 3)"]
    WEBAPP --> BLOB["sttarjetascontosopro<br/>Private Link"]
    subgraph AZ["Azure · West Europe"]
        FD
        WEBAPP
        API
        SQL
        BLOB
        VMS["vm-motor-disponibilidad-01<br/>snet-gestion"]
        GW["vgw-contoso-pro<br/>VpnGw1AZ"]
    end
    OFI["Barcelona and Palma offices<br/>10.100.0.0/16 · 10.101.0.0/16"] -->|site-to-site VPN| GW
    MARTA["Marta Ríos from home"] -->|point-to-site VPN| GW
    GW --> VMS

Cleanup, starting with the most expensive:

NET_GROUP="rg-contoso-red-pro"

# 1. Connections and gateway: FIRST OF ALL, it is what bills the most per hour.
az network vpn-connection delete -g "${NET_GROUP}" -n con-barcelona-pro
az network vpn-connection delete -g "${NET_GROUP}" -n con-palma-pro
az network vnet-gateway delete -g "${NET_GROUP}" -n vgw-contoso-pro
az network public-ip delete -g "${NET_GROUP}" -n ip-vgw-contoso-pro

# 2. Front Door.
az afd profile delete -g rg-contoso-reservas-pro --profile-name fd-contoso-global --yes

# 3. DNS zone (if it was a test one).
az network dns zone delete -g "${NET_GROUP}" -n contosoairlines.example --yes

# 4. Final check for residual spend across the whole subscription.
az network vnet-gateway list --query "[].{Gateway:name, SKU:sku.name, Group:resourceGroup}" -o table
az network public-ip list --query "[?ipConfiguration==null].{IP:name, Group:resourceGroup}" -o table
az disk list --query "[?diskState=='Unattached'].{Disk:name, GB:diskSizeGb}" -o table

Deleting the gateway takes several minutes. Do it before you leave, not afterwards: a VpnGw1AZ forgotten for a month costs more than the rest of this module's lab put together.

Common Mistakes and Tips

  • Creating the VPN gateway "just to try it" and forgetting it. It bills by the hour from minute one, connected or not. It is the most expensive cost mistake in the whole module.
  • Overlapping the P2S address pool with the Azure network or with the office network. The client connects, but reaches nothing. Reserve an exclusive range (172.16.30.0/24 at Contoso).
  • Using PolicyBased when RouteBased is needed. It supports neither P2S nor multiple tunnels, and the whole gateway has to be rebuilt.
  • Getting the ranges wrong in the local network gateway. If one office subnet is missing, that part of the network never reaches Azure and the symptom is "it half works".
  • Writing the VPN shared key into the script. It goes to Key Vault (04-03). A repository with an IPsec key in it is a security incident.
  • Assuming that ExpressRoute encrypts the traffic. It is a private circuit, not encrypted by default. If the requirement is end-to-end encryption, it has to be added.
  • Expecting Traffic Manager to fail over in seconds. It works through DNS: the clients' cache is in charge. For fast failover, Front Door.
  • Caching dynamic or personalized content in Front Door. A cached flight search result can be shown to another customer. Cache only static content.
  • Forgetting the alias record at the zone apex. You cannot use a CNAME at @; Azure DNS alias records are the solution.
  • Not budgeting for data transfer out. It is one of the first lines on the bill and the one fewest people anticipate. Tie it to the budget you created in lesson 01-03.
  • Tip: deploy the gateway with --no-wait and use the 30-45 minutes to configure everything else. And give it a specific budget alert.
  • Tip: document the table of ranges (Azure, offices, P2S) in the repository. During a connectivity incident at three in the morning, that document is worth more than any pretty diagram.

Exercises

Exercise 1: choosing the right connectivity

For each Contoso Airlines need, state which solution you would use and justify it:

  1. Marta Ríos administers the VMs from a hotel during a conference.
  2. The 30 workstations in the Palma office access the operations dashboard and the Azure Files share every day.
  3. Contoso decides to migrate the whole check-in system and move 8 TB of history over a weekend, and afterwards to maintain continuous low-latency synchronization.
  4. The airline opens branches at 18 airports, each with its own local network, and wants to connect them all without managing 18 gateways.

Exercise 2: global delivery

The passenger in Buenos Aires takes more than a second to see the flight search page.

  1. Which global delivery service would you choose, and why over the other two?
  2. Which content would you cache and which would you not? Justify the risk of getting it wrong.
  3. Write the health probe configuration for the origin group and explain each parameter.
  4. If Contoso added a deployment in North Europe, how would you configure it so that it was a backup and not active-active?

Exercise 3: auditing the data transfer bill

Nuria Peña, the finance lead, asks why the networking section of the bill has gone up 40% this quarter.

  1. List at least four sources of data transfer out in Contoso's current architecture.
  2. For each one, propose a concrete measure to reduce it.
  3. Which traffic in the architecture is free and worth explaining to Nuria so that she does not chase it?

Solutions

Solution 1:

Case Solution Justification
1. Marta from a hotel Point-to-site VPN with Entra ID authentication It is an individual machine and a changing location; there is no VPN device to configure and the existing MFA is reused
2. The 30 workstations in Palma Site-to-site VPN It connects the whole network transparently; and accessing Azure Files over SMB (port 445) practically requires private connectivity
3. Migrating 8 TB plus low-latency synchronization ExpressRoute Volume and predictable latency: moving 8 TB over a VPN across the internet is slow and unstable. It is planned weeks in advance and the VPN is kept as backup
4. 18 branches Azure Virtual WAN It manages the connections of many sites centrally, with built-in transit, instead of maintaining gateways, local objects and routes by hand

Solution 2:

  1. Azure Front Door. Over Azure CDN, because it is not only about caching static content: we also want to terminate TLS at the edge and accelerate dynamic content over Microsoft's backbone, plus the option of adding WAF (04-04). Over Traffic Manager, because that one only answers DNS queries and never touches the traffic: it would do nothing to reduce the connection-establishment latency, which is the bulk of the problem.

  2. Cacheable and non-cacheable:

Content Cache? Reason
/estatico/* (CSS, JS, images, logos) Yes, with a long TTL Identical for everyone and it changes rarely
/vuelos?origen=…&destino=… No It depends on real-time availability: caching it would sell seats that do not exist
/mi-reserva/* No Personal content; a caching mistake would show one passenger's data to another
The boarding pass PDF No It is served with a temporary SAS (lesson 02-04); caching it would defeat the protection

The risk of getting it wrong is twofold and serious: showing one passenger's personal data to another (a privacy and GDPR incident) and selling seats that no longer exist.

  1. The health probe:
az afd origin-group create \
  --resource-group rg-contoso-reservas-pro --profile-name fd-contoso-global \
  --origin-group-name og-reservas \
  --probe-request-type GET \        # the probe's method: GET, not HEAD, to exercise the application
  --probe-protocol Https \          # it is checked over the same channel the customer uses
  --probe-path "/salud" \           # the health endpoint created in lesson 02-03
  --probe-interval-in-seconds 30 \  # frequency: a balance between reaction and load
  --sample-size 4 \                 # the last 4 samples are evaluated
  --successful-samples-required 3 \ # with 3 good out of 4, the origin is considered healthy
  --additional-latency-in-milliseconds 50
  1. By adding the second origin to the same group with priority 2:
az afd origin create -g rg-contoso-reservas-pro --profile-name fd-contoso-global \
  --origin-group-name og-reservas --origin-name origen-northeurope \
  --host-name app-contoso-reservas-nor.azurewebsites.net \
  --priority 2 --weight 1000 --enabled-state Enabled

Front Door sends all the traffic to priority 1 while it is healthy and only fails over to 2 when the probes fail. With the same priority on both, the traffic would be split (active-active), which is precisely what Contoso ruled out on cost grounds in module 1.

Solution 3:

1 and 2. Sources of egress and measures:

Source of egress Reduction measure
Boarding pass PDFs downloaded by passengers Compress the PDF; serve it through Front Door (per-zone rate, and lower); avoid duplicate re-sends by email
Overnight synchronization with Barcelona's check-in system over the VPN Send only deltas instead of the full dump; compress the transfer
GZRS replication of sttarjetascontosopro to North Europe Review whether every container needs geo-redundancy; regenerable data can go in a separate ZRS account
Traffic between hub and spokes over peering Put the components that talk to each other the most in the same spoke
Website and API responses to internet clients Turn on compression and caching in Front Door; reduce the size of the JSON responses
  1. Free traffic, worth explaining so that nobody chases ghosts: all inbound data into Azure (boarding pass uploads, incoming requests, the initial migration load), and traffic within the same region and the same virtual network, such as the traffic from snet-web to snet-app or from the application to its database. In other words: processing data where it lives costs no transfer; moving it out does.

Conclusion

With this lesson you close module 2 and Contoso Airlines' platform is standing. You have solved the hybrid scenario: a point-to-site VPN with Microsoft Entra ID authentication so that Marta Ríos can administer from anywhere without exposing a single port, and a site-to-site VPN for Barcelona and Palma, with its four components — GatewaySubnet, a public IP, a virtual network gateway and a local network gateway — the choice of the VpnGw1AZ SKU with zone redundancy, and a single gateway serving every spoke of the hub-and-spoke. You know what ExpressRoute brings compared with a VPN — bandwidth, predictable latency, an SLA and not crossing the internet — its peering models, and why Contoso decides not to contract it yet. You know Azure Virtual WAN and the problem it solves when sites multiply. And in the other direction you have built global delivery: you understand where the thousand-plus milliseconds a passenger in Buenos Aires suffers come from, you have compared Front Door, CDN and Traffic Manager with clear selection criteria, you have published Contoso Bookings behind Front Door with a health probe, HTTPS redirection and caching of static content only, you have hosted the domain in Azure DNS with its alias record at the apex, and you know how to anticipate the data transfer out cost that will show up on the bill in module 8.

Recapping the whole module: you started by deploying virtual machines for the legacy availability engine, with their disks, their sizes and the difference between stopped and deallocated. Then you gave compute scaling and high availability with scale sets, automatic and scheduled rules, availability zones and a Load Balancer with health probes. You published Contoso Bookings and the Availability API on App Service, with plans, deployment slots and swap with warm-up so that new versions go live without interrupting sales. You stored the boarding passes in Azure Storage, settling the pending redundancy question — LRS in development, GZRS in production — and automating their lifecycle towards Cool and Archive. You built the virtual network with its subnets, NSGs, private DNS zones and private endpoints that took the database and the storage off the internet. And today you have joined that network with the offices and with the world.

You have compute, storage and networking. What is missing is what gives it all meaning: the data. The db-reservas database has been showing up in every lesson as a piece that exists but that you have neither designed nor deployed, and the decisions still to be made are not small ones: a relational database or a document store? Azure SQL Database, MySQL, PostgreSQL or Cosmos DB? What does each option cost, how does it scale and how does it recover if somebody deletes a table on a Friday afternoon?

In module 3, Azure Databases, we start exactly there: with the criteria for choosing the right data service — relational versus NoSQL, managed versus installed on a VM, cost versus performance — and then we will genuinely deploy Contoso Airlines' bookings database on Azure SQL Database, with its service tier, its backup, its point-in-time restore and its private connection to the network you have just built. See you there.

Azure Course

Module 1: Introduction to Azure

Module 2: Core Azure Services

Module 3: Azure Databases

Module 4: Security in Azure

Module 5: Azure DevOps

Module 6: Advanced Azure Services

Module 7: Monitoring and Management

Module 8: Cost Management and Optimization

Module 9: Case Studies and Best Practices

© Copyright 2026. All rights reserved