Why profile before you pick
In Level 1 you saw every Azure compute service on one page. The obvious next move is to pick one, and that is usually where things go wrong. Teams pick the service they already know, then discover months later that the job runs for 40 minutes, or needs Windows, or has to stay in one country. A workload profile prevents that. It's a short, standard record of what the workload actually needs. You fill it in once, and every later lesson in this course checks a service against it.
Think of it as a patient intake form at a clinic. The doctor doesn't choose a treatment until the form says "allergic to penicillin". Some answers on the form rule options out completely. Others only change the dose.
The main rule: write numbers, not adjectives. "Fast", "big" and "scalable" can't be checked against anything. "p99 under 200 ms", "64 GiB per process" and "peak 15× baseline" can.
The ten parts
| # | Entry | Record as |
|---|---|---|
| 1 | Compute type and memory | vCPUs, GiB RAM, GPU/accelerator model and count, per unit of work |
| 2 | Parallelism | tightly coupled / embarrassingly parallel / single process; number of nodes |
| 3 | Duration and state | run time per task (p50/p99); stateless or stateful; where state lives |
| 4 | Latency | p99 response target, or "batch: deadline by 06:00" |
| 5 | Scaling | baseline, peak, peak-to-baseline ratio, how quickly it ramps, scale to zero? |
| 6 | OS and licensing | Linux/Windows; container or not; licences tied to cores or hosts |
| 7 | Data location | where the input data sits, how much (TB), egress per run |
| 8 | Compliance | residency, certifications, isolation (shared vs dedicated hardware) |
| 9 | Team skills | what the team can run at 3 a.m.: VMs, Kubernetes, PaaS |
| 10 | Cost model | budget shape: steady, bursty, interruptible?, commitment appetite |
Two distinctions that narrow the field fast
Tightly coupled vs embarrassingly parallel. In embarrassingly parallel work the tasks never talk to each other. A Monte Carlo simulation that runs 10,000 independent scenarios is the classic case. You can spread the tasks over any number of machines, use cheap interruptible capacity, and retry a lost task on its own. Tightly coupled work is different: a fluid-dynamics solver whose processes swap boundary values over MPI thousands of times a second. Network latency between nodes then decides how fast the job runs. On Azure that means RDMA over InfiniBand, which only certain H-series and N-series VM sizes offer (Level 5 covers which). A tightly coupled job therefore drops almost every service from the map at once.
Stateless vs stateful. A stateless request handler can be killed, moved or copied at any moment, so it fits serverless and auto-scaling platforms. A stateful process can't be killed safely if it holds a session in memory, writes to local disk, or runs a 6-hour job with no checkpoints. It needs either long-lived hosts or a redesign that moves the state out to a database or storage. Before you count a workload as stateless, check where its state really lives.
Worked example: a risk-pricing engine
Keep the profile as a file in the repo, next to the code, so it gets reviewed like code:
# workload-profile.yaml: one file per workload, reviewed like code
name: risk-pricing-nightly
compute:
vcpus_per_task: 4 # measured with `top` during a sample run
gib_per_task: 16 # peak RSS observed was 11 GiB, plus headroom
accelerator: none # GPU port considered, not yet benchmarked
parallelism:
kind: embarrassingly_parallel # 10,000 scenarios, no inter-task traffic
tasks_per_run: 10000
duration_state:
task_runtime_p50: 3m
task_runtime_p99: 14m # ← note: longer than some serverless limits
state: stateless_tasks; results written to Blob Storage
latency:
target: "batch, finished by 06:00 UTC" # no per-request SLA
scaling:
baseline_cores: 0 # idle 20 h/day
peak_cores: 2000
ramp: "0→peak within 10 min at 01:00"
os_licensing:
os: linux
packaging: container (linux/amd64)
licences: none per-core
data:
input: 2 TB in Blob Storage, UK South
egress_per_run: 5 GB
compliance:
residency: UK only
isolation: shared hardware acceptable
team: strong Python and containers; no Kubernetes on-call
cost_model: interruptible OK (tasks retry); no commitment yet
Check every value against something you measured: a sample run, monitoring data, a licence contract. Mark anything you guessed as estimate. A guess that nobody labels gets treated as a requirement later.
Here is how the numbers come out of measurement:
# Peak-to-baseline ratio from an API's request metrics (example values)
baseline_rps=40 # median weekday traffic
peak_rps=600 # Black Friday p99 minute
echo "peak:baseline = $((peak_rps / baseline_rps)):1" # → peak:baseline = 15:1
A 15:1 ratio tells you that paying for peak capacity all day wastes most of the money. Fast automatic scaling becomes worth paying for.
Knockouts vs cost-changers
Most entries only shift cost or effort. A few remove services from the list entirely. In practice two or three knockouts do most of the cutting, and these are the usual ones:
- Duration. Azure Functions on the Consumption plan stops an execution after 10 minutes at most (default 5). On Flex Consumption the default is 30 minutes and there's no enforced maximum. HTTP-triggered functions on any plan must respond within 230 seconds. The pricing engine's 14-minute p99 task rules out the Consumption plan.
- OS and packaging. Azure Container Apps runs only Linux
linux/amd64images. A Windows-container workload can't use it, however well it fits otherwise. - Parallelism and hardware. Tightly coupled MPI needs InfiniBand-capable VMs. A GPU model you can't get in your region is a knockout too.
- Data location and compliance. "UK only" removes any service, size or feature that isn't offered in UK regions.
The cost-changers are team skills, cost model, and most latency and scaling entries. Kubernetes isn't impossible for a team without Kubernetes skills. It just costs more in hiring, training and operations.
Gotcha: run the knockouts first. If you score a service on cost and team fit before checking that it can run the job at all, you'll waste a review cycle on it.
Best practice: date the profile and re-check it when the workload changes. A new GPU code path or a new customer in another country can flip a knockout.
Key takeaways
- Fill in all ten entries with measured numbers: cores, GiB, p99 run time, p99 latency, peak-to-baseline ratio.
- Embarrassingly parallel work fits almost anywhere, including cheap interruptible capacity. Tightly coupled work needs low-latency interconnect and drops most services.
- Stateless work suits serverless and auto-scaling. Stateful work needs long-lived hosts or a redesign that moves the state out.
- Duration, OS/packaging, special hardware and data location/compliance are the usual knockouts. Apply them first.
- Team skills and cost model change effort and price. They rarely make a service impossible.