Why you need a profile before you pick anything
Ask five engineers which Azure service should front a web app and you'll get Front Door, Application Gateway, Load Balancer, "just a public IP" and "it depends". The last one is right, but only if you can say what it depends on. The connectivity profile is a written list of those things. You fill it in once per workload, and from here on every level scores a service against it. Think of it as a structural survey you get before buying a house: it doesn't choose the house for you, but it stops you buying one with no foundations.
The profile has twelve sections. You'll capture most of them in a single 45-minute meeting with the app owner, security and finance.
Step 1: Draw the flows, north-south vs east-west
Work out where traffic goes before you think about services.
- North-south traffic crosses the edge of your Azure estate: users on the internet reaching your app, your app calling a SaaS API, an office reaching Azure over VPN.
- East-west traffic stays inside it: web tier to API tier, a VM in one VNet calling a database in another, replication between two Azure regions.
The split matters because the two kinds of traffic are secured, inspected and billed differently. Internet egress is charged as data transfer. Traffic between peered VNets has its own per-GB charge. Anything that passes through a firewall or load balancer adds a processing charge on top.
Here is a worked example, "ShopCo": an online shop with UK and EU customers that runs in two regions and keeps stock data in an on-premises ERP.
# connectivity-profile.yaml: one file per workload, kept in the repo next to the IaC
workload: shopco-storefront
users:
who: public shoppers (UK 70%, EU 30%) + 40 staff in 2 offices
peak: 3,000 concurrent sessions, Black Friday x5
sites_and_regions:
primary: UK South
secondary: UK West # DR region
on_prem: Leeds datacentre (ERP)
flows:
- {name: shopper-to-web, dir: north-south, proto: HTTPS/443, est_gb_month: 2000}
- {name: web-to-api, dir: east-west, proto: HTTPS/443, est_gb_month: 800}
- {name: api-to-sql, dir: east-west, proto: TDS/1433, est_gb_month: 300}
- {name: api-to-erp, dir: north-south, proto: HTTPS/443, est_gb_month: 50} # hybrid
- {name: sql-replication, dir: east-west, proto: TDS/1433, est_gb_month: 500} # cross-region
Gotcha: teams usually list the shopper flow and forget replication, backups and log shipping. Those east-west flows often move more bytes than the users do.
Step 2: Turn adjectives into numbers
"Fast", "secure" and "always up" can't be compared against a service's limits. Rewrite each one until you could test it.
| Vague need | Measurable profile entry |
|---|---|
| "Fast" | p95 page response < 300 ms from London; api-to-sql < 5 ms round trip |
| "Handles big days" | 500 Mbps sustained, 2 Gbps burst at the edge |
| "Always up" | Availability target 99.95%; RTO 1 hour, RPO 5 minutes; survive loss of one zone |
| "Secure" | No public IPs on the data tier; all internet egress inspected; card data stays in the UK |
| "Connected to the office" | Private link to Leeds, 100 Mbps, failover to a backup path within 5 minutes |
Use real reference numbers as anchors. Microsoft documents the round-trip latency between availability zones in the same region as under about 2 ms. So a 5 ms api-to-sql target is reachable across zones, but you can't hit it across regions or across a hybrid link.
availability:
target: "99.95%"
rto: 1h # how long you may be down
rpo: 5m # how much data you may lose
failure_domain: zone # survive one zone; region loss = manual DR
hybrid:
sites: [leeds-dc]
bandwidth_mbps: 100
needs_private_path: true # decided here; *which* service comes later
segmentation:
model: zero-trust # deny by default, allow per flow
tiers: [web, api, data]
internet_exposure:
public_endpoints: [storefront]
ddos_concern: high # retail peak = attractive target
compliance:
data_residency: UK
regulated_data: [payment-card]
team_skills: {azure_networking: medium, bgp: low, terraform: high}
Best practice: record team skills honestly. A design that needs BGP tuning will hurt a team that rates its BGP as "low", even if the design is technically better.
Step 3: Sort every charge into three buckets
Azure networking charges come in three shapes. Comparisons are only fair when you keep them apart.
- Hourly. You pay while the resource exists, whether or not traffic flows. Example: Azure Firewall Standard is listed at $1.25 per deployment hour.
- Per GB processed. You pay for bytes that pass through a service. Examples: Firewall Standard $0.016/GB, Standard Load Balancer (regional) $0.005/GB.
- Data transfer. You pay for bytes that move between places. Inbound from the internet is free, and the first 100 GB a month of internet egress is free. After that, Zone 1 egress starts at $0.087/GB. Regional VNet peering costs $0.01/GB, and you're charged on both the outbound and inbound side.
These are US-dollar list prices from Azure's pricing pages in October 2026. They vary by region and change over time, so treat them as dated examples.
# cost_buckets.py: a rough monthly model for ShopCo's primary region
HOURS = 730
charges = [
# (item, bucket, monthly_cost)
("Firewall Standard running", "hourly", HOURS * 1.25), # 912.50
("Firewall data processed", "per-GB", 3000 * 0.016), # 48.00
("Load Balancer 5 rules", "hourly", HOURS * 0.025), # 18.25
("Load Balancer data processed","per-GB", 2000 * 0.005), # 10.00
("Internet egress 2,000 GB", "data transfer", (2000 - 100) * 0.087), # 165.30
]
for bucket in ("hourly", "per-GB", "data transfer"):
total = sum(c for _, b, c in charges if b == bucket)
print(f"{bucket:14} ${total:,.2f}")
hourly $930.75
per-GB $58.00
data transfer $165.30
Notice the pattern: for this workload the fixed hourly charge outweighs everything else. If you have a quiet dev environment, the lesson is to delete resources rather than leave them idle. If you're moving 50 TB a month, the per-GB buckets win instead, and that changes which service is cheapest.
Trade-off: one service can look cheap per hour and expensive per GB. Another can look the reverse. Only a profile with GB estimates tells you which one wins for you.
Using the profile from here on
Keep the file under version control, review it at every major release and mark guesses as est_. Each service lesson in this course ends by checking the service against these entries: does it meet the latency target, the failure domain, the compliance boundary and the skill level, and which cost bucket dominates?
Key takeaways
- Map flows first, and label each one north-south (it crosses the estate's edge) or east-west (it stays inside).
- Rewrite every adjective as a number: latency in ms, bandwidth in Mbps, availability %, RTO/RPO, and named compliance boundaries.
- Put every charge into hourly, per GB processed or data transfer, then compare services bucket by bucket.
- Inbound internet traffic is free and egress has a 100 GB monthly free allowance. VNet peering is billed on both sides.
- Record team skills and hybrid sites honestly, because they rule out designs as surely as limits do.