Nuria Peña, Contoso Airlines' finance lead, has spent months asking the same question in the steering committee and getting the same vague answer. When the migration was approved, somebody put "around €8,500 a month" on a slide. The average bill for the first real quarter was €17,500 a month: exactly double. Nobody lied. The estimate was simply built by adding up virtual machines and databases, which is what everybody estimates, and it left out everything else: the firewall, the bastion, the global entry point, log ingestion, data transfer out and a Kubernetes cluster whose nodes somebody believed were "part of AKS".
This lesson teaches you to estimate before you deploy. You will see how Azure really bills — which unit of measure each service family uses — the three types of cost almost nobody estimates, full use of the pricing calculator, Contoso's entire platform estimate rebuilt line by line, the total cost of ownership calculator for comparing against the Barcelona datacenter, why the same machine costs different amounts in two regions, how to automate estimates with the Retail Prices API and, above all, how you document the margin of error, because an estimate with no written assumptions is not an estimate: it is a number.
A warning about the prices in this lesson and across the whole module: every euro figure that appears here is illustrative and fictitious, chosen so that the orders of magnitude and the proportions teach something. Real Azure prices change frequently, and they vary by region, by currency, by offer type and by negotiated discounts. No figure in this module should be used to decide anything: always check the official Azure pricing calculator and your own commercial agreement.
Contents
- Why you estimate before you deploy
- How Azure really bills: units of measure
- The three costs almost nobody estimates
- The Azure pricing calculator, step by step
- The complete Contoso Airlines estimate
- The total cost of ownership calculator
- Pricing by region: the same VM at two prices
- The Retail Prices API
- The margin of error and the written assumptions
- Estimation as part of the design
- Common Mistakes and Tips
- Exercises
- Conclusion
- Why you estimate before you deploy
In your own datacenter, spending money takes a purchase order, a signature and several weeks. In Azure it takes three clicks. That is the whole difference, and it is enormous: control of spending has moved from the purchasing department to the engineer's keyboard, and nobody told the engineer.
The consequence is a pattern that repeats in every organization that migrates:
| Moment | What happens | Cost of correcting it |
|---|---|---|
| Design | The architecture and its service tiers are chosen | Almost nil: it is changing a decision in a document |
| Deployment | The resources are created with Bicep | Low: change a parameter and redeploy |
| First month | The bill arrives and surprises everybody | Medium: resources have to change in production |
| Sixth month | Spending has normalized and there is data on top of it | High: migrations, windows, risk |
Estimation is the only lever that acts on the first row. Put another way: the hardest bill to correct is the one you have already caused. A redundancy level chosen carelessly on day one turns into a data migration the following year.
And there is a second reason, less obvious and more important: estimating forces you to understand the architecture. When Marta Ríos redid Contoso's estimate with the calculator, she discovered three things that had been sitting there for months without anybody seeing them — a geo-replica of the database that cost almost as much as the primary, an AKS node pool sized for a load test that finished in March, and a VPN gateway with no active connections. Estimating is auditing the design with a calculator in your hand.
- How Azure really bills: units of measure
The underlying error in Contoso's failed estimate was a mental one: Azure was pictured as a catalog of machines with a monthly price. Azure bills units of consumption, and each service family uses its own. Until you have internalized the following table, you cannot estimate anything.
| Family | Main unit of measure | Other units that also bill | Example at Contoso |
|---|---|---|---|
| Compute (VM, VMSS) | Instance hour while running (deallocated does not bill) |
Managed disks (GB-month, IOPS), public IP, OS license | vmss-api-disponibilidad-pro |
| App Service | Plan hour, not application hour | Certificates, domains, extra slots depending on tier | plan-contoso-reservas-pro |
| Containers (AKS) | Hour of each node (VM) + disks | Standard control plane, load balancer, egress | aks-contoso-operaciones |
| Container Apps / Functions consumption | vCPU-second and GiB-second + executions | Minimum replicas always running | ca-motor-disponibilidad |
| Storage | GB-month per access tier | Transactions, data retrieval, tier change | sttarjetascontosopro |
| SQL Database (vCore) | vCore-hour provisioned or vCore-second serverless | Storage GB-month, LTR backups, secondary replica | db-reservas |
| Cosmos DB | Request units per second (RU/s) hour | Storage GB-month, backups, each additional region | cosmos-contoso-tarifas-pro |
| Synapse serverless | TB of data read per query | Lake storage, pipelines per activity | syn-contoso-analitica-pro |
| Log Analytics | GB ingested | GB-month retained, table plan, queries over the archive | log-contoso-pro |
| Networking | GB of data transfer out (egress) | Firewall hour + GB processed, bastion hour, gateway hour | fw-contoso-hub-pro |
| Messaging | Operations or messaging/throughput units per hour | Extra entities, extended retention | sb-contoso-pro |
| Logic Apps | Action execution | Enterprise connectors with their own rate | logic-contoso-retrasos-pro |
| AI / Azure OpenAI | Token in and out | Provisioned throughput units, if contracted | oai-contoso-pro |
| Backup | Protected instance + GB stored | Geo-redundancy, cross-region restore | rsv-contoso-pro |
Three readings of this table that change how you estimate:
- The unit is not always the resource you can see. You do not pay for
app-contoso-reservas-pro; you pay forplan-contoso-reservas-pro, and it makes no difference whether you host one application or five. - Almost everything has a second unit. Storage has GB and transactions. The firewall has hours and gigabytes processed. The database has compute and storage and backups. Estimating only the main unit systematically produces low estimates.
- Some units are not proportional to the usage you perceive. A badly written query in Synapse serverless reads 2 TB and costs more than a whole day of virtual machines, even though the user only clicked "refresh".
- The three costs almost nobody estimates
Of Contoso's failed estimate, nearly half the deviation came from three items that did not even appear in the original spreadsheet.
Data transfer out (egress). Traffic into Azure is free; traffic out of Azure to the internet is not. Nor is traffic between regions free, and in many cases neither is traffic between availability zones. As module 2 anticipated, this is the usual surprise on the bill, because it does not show up as a resource: there is no object called "data transfer out" in the portal for you to look at. At Contoso it is produced by all of this at once: every boarding pass downloaded by a passenger, every response from the Availability API to the external aggregators, the replication of db-reservas to North Europe, the geo-replication of acrcontosopro and the nightly exports to the local billing system. You estimate it with a simple rule: how many objects leave per month × average size, and you write the assumption down.
Transactions and operations. The GB of a storage account get estimated properly; the transactions almost never do. And on workloads with many small objects — which is exactly the boarding pass case — transactions can exceed storage. Worse still: cold tiers make the GB-month cheaper and the transaction more expensive, so a badly tuned lifecycle rule that moves data still being read frequently to Cool can actually raise the bill. The same applies to Key Vault operations, Cosmos DB requests and Defender for Cloud operations over Storage.
The "free" features that drag a paid resource behind them. This is the most treacherous one, because the service advertises zero cost and delivers it:
| "Free" service | What you do pay for |
|---|---|
| Azure Policy | Nothing for the policy, but a DeployIfNotExists effect creates paid resources |
| Diagnostic settings | The setting is free; the ingestion into log-contoso-pro is not |
| Microsoft Entra ID (base tier) | Conditional Access and Identity Protection require paid tiers |
| Defender for Cloud (basic CSPM) | The per-workload plans do cost (module 4) |
| Azure Advisor | Genuinely free, with no small print (08-04) |
| Azure Monitor alerts | Resource health alerts are free; metric and log alerts are billed per rule and per series |
| Resource groups, tags, ARM | Really free |
| Automation account | The account costs nothing; the execution minutes above the free allowance do |
The rule to burn into your memory: whenever you switch something free on, always ask what consumption it generates downstream. The diagnostic settings from module 7 are free and produced the third most expensive item on the platform.
- The Azure pricing calculator, step by step
The Azure pricing calculator (azure.microsoft.com/pricing/calculator) is a public tool, no account required, that lets you build a complete estimate. It is deceptively simple, and using it well takes method.
flowchart LR A["Search for and add<br/>the services"] --> B["Configure each one:<br/>region, tier, quantity,<br/>hours and units"] B --> C["Group by<br/>component or environment"] C --> D["Apply currency,<br/>offer and discounts"] D --> E["Save, share<br/>and export to Excel"] E --> F["Review with the team<br/>and with Nuria"] F -->|"assumptions missing"| B
The procedure Marta follows:
- Search for the service and add it. The calculator has a catalog by category and a search box. Add every service in the architecture, including the ones that "cost nothing" — so there is a record that they were considered.
- Configure region, tier and quantity. This is 90% of the work. For a VM: region, operating system, instance type, number of instances, hours per month (730 for 24x7, around 176 for business hours only), disk type and number of disks, and the savings option (pay-as-you-go, one-year or three-year reservation, savings plan, spot). That selector is what connects this lesson to 08-03.
- Group by component. The calculator lets you create groups and rename them. Contoso uses one group per architecture block:
Web front end,Availability API,Data,Networking and security,Observability,Integration and AI,Development. Without groups, a forty-line estimate is unreadable and nobody reviews it. - Set currency, billing region and licensing program. The calculator applies the offer type (pay-as-you-go, Enterprise, CSP) and lets you enter a negotiated discount percentage.
- Save and share. With a Microsoft account the estimate is saved and you get a link. That is what gets attached to the architecture review.
- Export to a spreadsheet. The export button produces an
.xlsxwith one row per line, which is the format Nuria can work with and compare month to month.
Two usage warnings. The first: the calculator does not know your workload; it only multiplies whatever you tell it. If you put 730 hours for a machine that will actually be running for 200, that is not the tool's fault. The second: there are services whose cost cannot be estimated without prior data — data transfer out, transactions, tokens, GB ingested — and for those, the calculator forces you to enter a quantity, and that quantity is an assumption you have to document (section 9).
- The complete Contoso Airlines estimate
Marta rebuilt the estimate of the platform exactly as it stands today. The result, in illustrative and fictitious euros per month:
| Group | Line | Assumed configuration | € / month |
|---|---|---|---|
| Web front end | plan-contoso-reservas-pro + plan-contoso-api-pro |
Premium v3, 3 and 2 instances, zone redundancy, 730 h | 1,930 |
| Availability API | vmss-api-disponibilidad-pro |
Average of 6 instances out of the autoscale range of 2-20 | 1,320 |
| Availability API | cae-contoso-pro + ca-motor-disponibilidad |
Environment + 1 minimum replica always running | 240 |
| Containers | aks-contoso-operaciones |
sistema (3) + aplicaciones (4) nodes + lotes on spot |
1,980 |
| Containers | acrcontosopro |
Premium with geo-replication | 90 |
| Development | Development plans and VM | Dev App Service + vm-motor-disponibilidad-dev switched off at night |
285 |
| Storage | sttarjetascontosopro |
GZRS, 4 TB, lifecycle to Cool after 30 days, transactions | 420 |
| Storage | stlagocontosopro |
Data Lake, 12 TB, mixed tiers | 280 |
| Storage | stoperacionescontosopro + sttarjetascontosodev |
ZRS 1 TB + LRS 300 GB | 75 |
| Data | db-reservas (primary) |
General Purpose vCore, 8 vCores, zone redundancy, 500 GB | 1,480 |
| Data | fg-contoso-reservas replica in North Europe |
Readable secondary of the failover group | 1,180 |
| Data | sql-contoso-reservas-dev + cosmos-contoso-tarifas-pro |
Serverless with auto-pause + autoscale, average 1,400 RU/s | 255 |
| Data | mysql-contoso-portal-pro + psql-contoso-tripulaciones-pro |
Flexible, 2 vCores each | 345 |
| Data | syn-contoso-analitica-pro |
Serverless SQL per TB read + occasional sqlpool-contoso |
400 |
| Networking and security | fw-contoso-hub-pro |
Azure Firewall: hours + GB processed | 1,010 |
| Networking and security | fd-contoso-global + wafcontosoglobal |
Front Door Premium + WAF rules | 385 |
| Networking and security | bastion-contoso-pro |
Standard tier, 730 h | 205 |
| Networking and security | vgw-contoso-pro + private endpoints |
VPN + 14 private endpoints | 235 |
| Networking and security | Data transfer out | ~4.5 TB/month to the internet + cross-region replication | 700 |
| Observability | log-contoso-pro + ai-insights-contoso-pro |
~42 GB/day ingested + per-table retention | 1,500 |
| Observability | Defender for Cloud | SQL, Storage and Key Vault plans | 310 |
| Observability | rsv-contoso-pro + bv-contoso-pro |
Protected instances + GB, 30 days, GRS | 465 |
| Integration | sb-contoso-pro + evhns-contoso-telemetria-pro + evgt-contoso-reservas-pro |
Service Bus Premium 1 unit, Event Hubs 2 TU | 780 |
| Integration | func-contoso-tarjetas-pro + logic-contoso-retrasos-pro |
Premium EP1 plan + Logic Apps actions | 335 |
| AI | oai-contoso-pro + ai-contoso-pro |
Cost per token + AI services | 730 |
| Cross-cutting | kv-contoso-pro, aa-contoso-operaciones, Azure DevOps and other minor items |
Operations, minutes, licenses, contoso-paquetes, IPs, DNS |
515 |
| Estimated total | €17,450/month |
Where each block comes from deserves comment, because that is where the learning is:
- The five lines that surprise people are, in this order:
log-contoso-pro(€1,500, more than half the entire web platform),fw-contoso-hub-pro(€1,010, which bills per hour and per gigabyte processed whether traffic flows or not), theaks-contoso-operacionescluster (€1,980, because the nodes are virtual machines you pay for in full),bastion-contoso-pro(€205 for a service used fifteen minutes a day) andfd-contoso-global(€385 for the Premium tier the WAF requires). - The
db-reservasreplica costs €1,180, 80% of the primary. That is the explicit price of the recovery decision from module 7, and now it can be seen in euros: exactly the kind of data that makes an honest conversation with the business possible. - Data transfer out (€700) does not correspond to any resource. Nobody would have estimated it without the table in section 2.
- The whole development environment is €285 thanks to the
Detener-IniciarEntornosDevrunbook and the serverless tier with auto-pause. Without those two decisions it would be around €1,100.
Compared with the €8,500 on the original slide, the difference is explained almost entirely by five lines: AKS, Log Analytics, the firewall, the database replica and data transfer out. None of them is a resource the team ever "asked for"; they are all consequences of correct architecture decisions that nobody translated into money.
- The total cost of ownership calculator
Nuria asked the inevitable question: "wasn't the Barcelona datacenter cheaper?". To answer it there is the total cost of ownership (TCO) calculator, a different tool from the pricing one: you describe the on-premises infrastructure — servers, cores, memory, storage, bandwidth, licenses — and it returns a multi-year comparison against the Azure equivalent.
The value of the tool is not in the number it produces, but in the fact that it forces you to include the costs local accounting never charges to the project:
| On-premises cost | Is it usually included? | Comment |
|---|---|---|
| Hardware (servers, storage array, network) | Yes | The only thing almost everybody counts |
| Virtualization and OS licenses | Sometimes | And their annual maintenance |
| Electricity and cooling | Rarely | Typically 10-20% of the hardware cost per year |
| Space, raised floor and UPS | Almost never | Even if the building is your own, it has an opportunity cost |
| Operations staff | Almost never | On-call rotas, patching, replacing disks |
| Refresh every 4-5 years and overcapacity | Badly | You buy for the peak and pay all year, every cycle |
| The cost of downtime | Never | Without geo-redundancy, the risk is a deferred cost |
With the TCO calculator and those adjustments, Contoso's comparison came out like this (illustrative and fictitious annual figures):
| Scenario | Annual cost | Comment |
|---|---|---|
| Barcelona datacenter, visible cost | €190,000 | What appeared in the IT budget |
| Barcelona datacenter, real adjusted cost | €340,000 | With power, staff, space, refresh and overcapacity |
| Azure, current platform without optimization | €209,400 | €17,450 × 12 |
| Azure, after the optimization in module 8 | ~€150,600 | A preview of 08-05 |
The conclusion Contoso wrote down, and one worth copying verbatim into any report: the comparison is not "Azure is cheaper", it is "Azure is cheaper than an honestly accounted-for datacenter, and on top of that it turns capital investment into operating expense, eliminates overcapacity and provides capabilities — geo-redundancy, scaling in minutes, managed services — that the datacenter did not have at any price". Comparing hardware alone against Azure invoices is the most common way of lying to yourself.
- Pricing by region: the same VM at two prices
The same instance size costs different amounts in West Europe, in North Europe, in Sweden Central or in the United States. The causes are real: the cost of energy and land, taxes, datacenter maturity, exchange rates and local demand.
An illustrative and fictitious index taking West Europe as 100 for the same VM:
| Region | Price index | Comment |
|---|---|---|
| West Europe | 100 | Contoso's primary region |
| North Europe | 96 | Secondary region of the pair |
| Sweden Central | 89 | Cheaper, plentiful energy |
| East US | 87 | Usually among the most economical |
| Brazil South | 128 | Taxation and infrastructure |
The temptation is obvious: move workloads to the cheapest region. Before doing so, four brakes Contoso applied:
- Latency. The bookings website serves European passengers. A 13% saving on compute does not make up for 120 ms extra on every purchase.
- Data residency. Personal data about passengers and crews does not leave the EU. That is a legal constraint, not a preference, and it is enforced by the allowed-regions policy from module 4.
- Cross-region data transfer out. Splitting components that talk to each other a lot across two regions turns free internal traffic into billed cross-region traffic.
- Service availability. Not every service and not every size exists in every region, and neither do availability zones.
The practical rule: the region is chosen on latency, data residency and service availability, and price is used only as a tie-breaker, or for workloads that have none of those constraints — a nightly batch process with no personal data, for example.
- The Retail Prices API
To automate estimates — or to compare regions without opening the calculator forty times — Azure publishes the Retail Prices API, which is public, requires no authentication and costs nothing. It returns official list prices, without your negotiated discounts.
# Hourly price of a VM size in West Europe, in euros
curl -s "https://prices.azure.com/api/retail/prices?currencyCode='EUR'&\$filter=\
serviceName eq 'Virtual Machines' and armRegionName eq 'westeurope' and \
armSkuName eq 'Standard_D4s_v5' and priceType eq 'Consumption'" \
| jq -r '.Items[] | select(.productName | contains("Windows") | not)
| "\(.armRegionName)\t\(.meterName)\t\(.retailPrice) \(.currencyCode)"'The $filter parameter uses OData syntax and accepts serviceName, armRegionName, armSkuName, meterName, priceType (Consumption, Reservation, DevTestConsumption) and reservationTerm. The select clause in jq discards the Windows-licensed variants, which come mixed in with the Linux ones and are the most common misreading.
An equivalent loop over several regions — the use that pays off most — substitutes armRegionName eq '$REGION' inside a for REGION in westeurope northeurope swedencentral eastus, takes [.Items[].retailPrice] | min and multiplies by 730 hours to get the average month. The response is paginated through the NextPageLink field, so broad queries have to iterate. A very practical use: keep a script in contoso-infra that, on every pull request that modifies a .bicep file, looks up the prices of the declared SKUs and posts the estimate as an automatic comment on the pull request itself (section 10).
{
"currencyCode": "EUR",
"retailPrice": 0.2048,
"unitOfMeasure": "1 Hour",
"armRegionName": "westeurope",
"armSkuName": "Standard_D4s_v5",
"serviceName": "Virtual Machines",
"priceType": "Consumption",
"meterName": "D4s v5"
}Every item returned has this shape. Look at unitOfMeasure: it is the key to not being wrong by three orders of magnitude. Some meters are expressed in "1 Hour", others in "1 GB/Month", others in "10K" operations and others in "1M" tokens. Multiplying without reading that column is the classic mistake of anybody automating estimates for the first time.
- The margin of error and the written assumptions
An estimate is a model, and every model has error. The difference between a professional estimate and an improvised number is that the first one declares its error and its assumptions.
The components of Contoso's estimate are classified by predictability:
| Type of cost | Examples | Predictability | Recommended margin |
|---|---|---|---|
| Fixed | App Service plans, firewall, bastion, gateway | Very high | ±5% |
| Semi-fixed | AKS base nodes, provisioned database | High | ±10% |
| Bounded variable | VMSS with autoscale 2-20, Cosmos with autoscale | Medium | ±25% |
| Open variable | Data transfer out, transactions, GB ingested, tokens | Low | ±50% |
And this is how you estimate the variable part, which is where everybody gives up:
- Autoscale: you do not estimate the maximum or the minimum, but the expected hourly profile. Contoso documented: 2 instances from 00:00 to 07:00, 6 from 07:00 to 22:00, and an
apertura-temporada-veranoprofile averaging 14 for three weeks. The weighted monthly average came out at 6, and that is why the line says 6 and not 20. - Transactions and data transfer out: these are estimated from the business, not from the infrastructure. "92,000 bookings a month × 1.4 boarding passes per booking × 180 KB" gives the gigabytes of boarding pass egress; the rest is bounded with a factor.
- Tokens: consumption per interaction × expected interactions, with a hard limit configured on the service so that the error is not unbounded.
Contoso's buffer: on top of the €17,450 base, a 15% contingency gives €20,070/month, and that is the figure that went to the committee. It is deliberately conservative, and it answers a real asymmetry: falling short on an estimate costs credibility with finance; overshooting slightly produces good news. The written rule was: "you budget the estimate with the buffer; you chase the base estimate".
The assumptions go in the document, not in somebody's head:
{
"estimate": "contoso-platform-2026-08",
"currency": "EUR",
"primary_region": "westeurope",
"prices_valid_as_of": "2026-08-01",
"monthly_base_total": 17450,
"buffer_pct": 15,
"budgeted_total": 20070,
"assumptions": [
"Monthly bookings: 92,000, peaking at 148,000 in August",
"vmss-api-disponibilidad-pro: average of 6 instances (hourly profile documented)",
"Data transfer out to internet: 4.5 TB/month, cross-region replication included",
"log-contoso-pro: 42 GB/day ingested, current per-table retention",
"oai-contoso-pro: 40 million tokens/month, hard limit configured",
"No reservations or savings plans purchased (see 08-03)",
"Official list prices, no commercial agreement discount"
],
"risks": ["Summer may double egress and VMSS", "sqlpool-contoso not paused"]
}That file lives next to the templates in contoso-infra. Its value shows up three months later, when the bill does not add up: you compare the assumption with reality and you know what failed, not just how much.
- Estimation as part of the design
For cost to stop being a surprise, it has to be built into two moments of the process, not into an annual review.
In the architecture review. No proposal is approved at Contoso without an attached estimate with its assumptions and, when there are alternatives, without a comparison table. A real example from the design of the Availability API:
| Alternative | Illustrative € / month | Latency | Operations | Decision |
|---|---|---|---|---|
| VMSS with autoscale | 1,320 | Low and stable | Medium: patches, images | Chosen: sustained, predictable load |
| Container Apps | 890 | Low, with occasional cold start | Low | Ruled out because of cold start at season opening |
| Functions on a consumption plan | 410 | Variable | Very low | Ruled out: the API is sustained, not sporadic |
Notice that the cheapest option did not win, and that is the point: the estimate does not decide, it informs. What is unacceptable is deciding without one.
In the infrastructure pull request. Every change to a .bicep file in contoso-infra (05-06) goes through an automated check that compares the declared SKUs against the main branch and comments on the impact:
# Simplified: extract SKUs from the templates and ask the Retail Prices API
grep -rhoP "(?<=sku:\s')[A-Za-z0-9_]+" ./infra/*.bicep | sort -u | while read -r SKU; do
P=$(curl -s "https://prices.azure.com/api/retail/prices?currencyCode='EUR'&\$filter=\
armSkuName eq '$SKU' and armRegionName eq 'westeurope' and priceType eq 'Consumption'" \
| jq -r '[.Items[].retailPrice] | min // empty')
[ -n "$P" ] && echo "| \`$SKU\` | €$P/h | €$(echo "$P * 730" | bc)/month |"
doneThe output is posted as a comment on the pull request, with the markdown table already formatted. The cultural effect is bigger than the technical one: whoever proposes a change sees its price before anybody asks, and the conversation about cost happens at the moment when correcting it is free.
Common Mistakes and Tips
- Estimating only compute and databases. That is exactly the mistake that doubled Contoso's bill. Walk through the units table in section 2 service by service.
- Forgetting data transfer out. It has no resource of its own, it does not appear in the portal as an object and it is usually one of the top ten items.
- Confusing the resource with the billed unit. You pay for the plan, not the application; the nodes, not the cluster; the vCore-hour, not the database.
- Putting 730 hours against everything, or estimating the autoscale maximum. The first inflates environments that are switched off at night; the second produces figures nobody believes and discredits the entire estimate. Estimate the profile, and declare the maximum as a risk.
- Misreading
unitOfMeasurein the API. "1M tokens" and "1K operations" live side by side in the same response. - Switching something free on without looking downstream. Diagnostic settings are free; the ingestion they cause is not.
- Tip: group the estimate by architecture component, not by Azure service. Nobody argues about "Storage"; everybody argues about "how much the Availability API costs".
- Tip: save the estimate with a link and export it to a spreadsheet the day you make it, and revisit it when the architecture changes, not when the bill arrives.
Exercises
Exercise 1. Using the official calculator — with your region and your currency — estimate a development environment equivalent to Contoso's: a basic App Service plan, a serverless SQL database with auto-pause, a 200 GB LRS storage account and a 2 vCPU VM running during business hours only. Group by component, export it and note which three assumptions you had to invent.
Exercise 2. Contoso Miles (centro-coste=CC-2077) is about to launch: a website on App Service, PostgreSQL flexible, receipt blobs, a Function that calculates points, an Event Grid and a Log Analytics dashboard. Build the list of all the units of measure that will have to be estimated, marking which are fixed, bounded variable and open variable, and what margin you would apply to each group.
Exercise 3. A colleague proposes moving vmss-api-disponibilidad-pro from West Europe to East US because "it costs 13% less". Write the technical and economic response: which new costs appear, which constraints rule it out, and which Contoso workloads would be legitimate candidates for that move.
Solutions
Solution 1: the exercise matters for the assumptions, not for the total. The three you inevitably have to invent are: (1) VM hours — 176 hours a month with the business-hours pattern of 8 h × 22 days, against the 730 the calculator proposes by default; (2) compute seconds for the serverless database, which depend on how many hours a day the team works and on the auto-pause window configured, and which in development usually land at 15-25% of the month; and (3) storage transactions, which the calculator asks for as write, read and list operations and which in development nobody has ever measured. There are also two costs almost certainly omitted that have to be added: the VM's managed disk, which is billed even when the machine is deallocated, and its public IP if it has one. Sanity check: in an environment like this, the disk and the database usually weigh more than the compute, precisely because the compute gets switched off and the storage does not.
Solution 2: units by service and their classification. Fixed (±5%): App Service plan hour; vCore-hour and GB-month of PostgreSQL flexible if provisioned; the high-availability replica if enabled. Bounded variable (±25%): executions and GB-seconds of the Function if on a consumption plan — bounded because the number of redemptions has a known ceiling; Event Grid operations; GB-month of the blobs, which grow predictably at the pace of redemptions. Open variable (±50%): storage transactions, which with small receipts can exceed the GB-month; GB ingested into log-contoso-pro by the project's diagnostic settings, which is the most underestimated item; and data transfer out from receipt downloads. Free services with downstream consumption that have to be declared even at zero: Event Grid has a generous free allowance, tags and policies cost nothing, but the diagnostico-app-service assignment inherited from the "Base de gobernanza de Contoso" initiative will generate ingestion from day one. Recommended overall margin: 15% on the total, with the assumptions about monthly redemptions and average receipt size written into the document.
Solution 3: the 13% saving applies only to the compute line (€1,320 → around €1,150, roughly €170 a month), and against that come new costs: cross-region data transfer out for every availability query the VMSS makes to db-reservas and cosmos-contoso-tarifas-pro, which stay in West Europe — traffic that is internal and free today would start being billed and, at the API's volume, would comfortably eat the saving; latency of a transatlantic round trip on every request, degrading the availability shown to the passenger; and double operations, because you would have to replicate the network, NSGs, private endpoints, bastion, fw-contoso-hub-pro rules and diagnostic settings in a second region. The constraint that closes the discussion is compliance: passenger data does not leave the EU, and the allowed-regions policy from module 4 will deny the deployment. Workloads that would be legitimate candidates: nightly batch processes over already anonymized data, self-hosted build agents for contoso-reservas-ci — which can also run on spot instances (08-03) — and one-off training runs or load tests with no personal data. General rule: you move on price whatever has no critical latency, no regulated data and no chatty conversation with resources in another region.
Conclusion
You now know why estimation is the only lever that acts while correcting is still free, and why Contoso's error — doubling the forecast — was not one of arithmetic but of mental model: Azure is not a catalog of machines with a monthly price, but a set of units of consumption. You have the table of those units by service family — instance hour, plan hour, GB-month, transaction, request unit, TB read, GB ingested, GB of data transfer out, execution, token, protected instance — the warning that almost everything has a second unit nobody estimates, and the three costs that always get forgotten: data transfer out, which has no resource to look at; transactions, which on small objects exceed storage; and the "free" features that drag consumption along downstream, with diagnostic settings as the perfect example.
You can use the pricing calculator with method — search, configure region, tier, quantity and hours, group by component, set currency and offer, save, share and export — and you have seen Contoso's complete estimate: an illustrative €17,450/month, with the five surprising lines identified — Log Analytics, the firewall, the AKS nodes, the bastion and Front Door — plus the db-reservas replica, which costs 80% of the primary and puts an explicit price on the recovery decision from module 7. You know how to use the total cost of ownership calculator and which hidden datacenter costs have to be added for the comparison to be honest: power, staff, space, refresh, overcapacity and risk. You understand why the same VM costs different amounts in each region and why the region is chosen on latency, data residency and availability, with price only as a tie-breaker; and you can automate it with the Retail Prices API, always watching unitOfMeasure. Above the tooling you carry what turns a number into an estimate: the declared margin of error, the way to estimate the variable part from the hourly profile and from the business instead of from the theoretical maximum, the 15% buffer that took €17,450 to the €20,070 budgeted, and the file of assumptions and risks versioned alongside the templates.
But an estimate, however good, is still a hypothesis. Nuria's question — "why does the bill go up every month?" — can only be answered with real data: what was spent, on which resource, by which team, on which day and why. That is Azure Cost Management, and it is the next lesson: the billing hierarchy and how it differs from the resource one, cost analysis grouped by service, location, resource group and tag — where the discipline of centro-coste=CC-1042 sown in module 1 and enforced by the hereda-centro-coste policy from module 4 finally pays off — budgets with their automated alerts, allocation between teams, exports to stlagocontosopro and anomaly detection. We move from estimating cost to measuring it.
Azure Course
Module 1: Introduction to Azure
- What Is Azure?
- Service Models, Regions and Availability Zones
- Creating and Setting Up Your Azure Account
- A Tour of the Azure Portal
- Azure Resource Manager: Subscriptions, Resource Groups and Tags
- Azure CLI, PowerShell and Cloud Shell
Module 2: Core Azure Services
- Azure Virtual Machines
- Compute Scaling and High Availability
- Azure App Service
- Azure Storage: Blobs, Files, Queues and Tables
- Azure Networking: Virtual Networks, Subnets and NSGs
- Hybrid Connectivity and Global Delivery
Module 3: Azure Databases
- Choosing the Right Data Service
- Azure SQL Database
- Azure Cosmos DB
- Azure Database for MySQL
- Azure Database for PostgreSQL
- Data Analytics: Data Lake, Data Factory and Synapse
Module 4: Security in Azure
- Microsoft Entra ID and Identity Management
- RBAC and Managed Identities
- Azure Key Vault
- DDoS Protection and Web Application Firewall
- Microsoft Defender for Cloud
- Governance and Compliance with Azure Policy
Module 5: Azure DevOps
- Introduction to Azure DevOps
- Azure Repos
- Azure Pipelines: Continuous Integration
- Continuous Deployment with Environments and Approvals
- Azure Artifacts
- Infrastructure as Code with Bicep
Module 6: Advanced Azure Services
- Containers in Azure: Container Registry and Container Apps
- Azure Kubernetes Service (AKS)
- Azure Functions
- Azure Logic Apps
- Messaging and Events: Service Bus, Event Grid and Event Hubs
- Azure AI Services
Module 7: Monitoring and Management
- Azure Monitor: Metrics, Alerts and Dashboards
- Log Analytics and KQL Queries
- Application Insights
- Azure Automation and Runbooks
- Backup and Disaster Recovery
Module 8: Cost Management and Optimization
- Pricing Calculator and Cost Estimation
- Azure Cost Management: Analysis, Budgets and Alerts
- Reservations, Savings Plans and Azure Hybrid Benefit
- Azure Advisor
- Optimization Strategies and FinOps Culture
