Why profile before you pick
In Level 1 you saw every Google Cloud compute service on one page. That raises the next question: which one is right for your workload? You can't answer that until you can describe the workload in a fixed, repeatable way. That description is the workload profile. Every service lesson from here on is scored against it, and so is the final selection scorecard.
Think of it as a building survey before you choose a crane. A survey that says "the building is fairly tall" is no use. One that says "42 m, 3.1-tonne maximum lift, no road access on Sundays" decides the crane for you. Profiles work the same way. Write numbers, not adjectives. "Needs lots of memory" rules nothing out. "Peak 118 GiB per process" rules out a lot.
The twelve fields
Here is the template. Keep it in the repository alongside the code, because it changes as the workload changes.
# workload-profile.yaml: one per workload, versioned with the code
name: risk-montecarlo-nightly
compute:
cpu_cores_per_unit: 4 # measured, not guessed
accelerator: none # or e.g. "nvidia-l4, 24 GB VRAM"
memory_gib_per_unit: 6 # peak, from a real run
coupling: embarrassingly_parallel # or tightly_coupled
duration:
per_unit_minutes: 35 # p95 of a real run
state: stateless # stateless | checkpointable | stateful
latency: batch_deadline_06:00 # or "p99 < 200 ms" for interactive work
scaling: 0 -> 2000 units nightly, 0 by day
os_and_licensing: linux, no per-core licences
data_location: inputs in a GCS bucket in europe-west2, must stay in UK/EU
compliance: internal model; no regulated data
team_skills: Python, Docker; no Kubernetes on-call
cost_model: lowest cost per run; tolerates retries
Each field does a job:
| Field | Question it answers | Typical evidence |
|---|---|---|
| CPU / accelerator / memory | How big is one unit of work? | /usr/bin/time -v, nvidia-smi, profiler |
| Coupling | Do the units talk to each other while they run? | Code review: MPI, NCCL, shared state |
| Duration and state | How long does a unit run, and what is lost if it dies? | p95 runtime, checkpoint support |
| Latency | Does a person or a system wait for each answer? | SLO, deadline |
| Scaling | How far does demand swing, and how fast? | Traffic or queue graphs |
| OS and licensing | Which operating system, and which licence terms? | Licence agreements |
| Data location | Where does the data live, and where may it go? | Bucket regions, legal advice |
| Compliance | Which rules apply? | Certifications required |
| Team skills | What can the team run at 3 a.m.? | Honest headcount |
| Cost model | Steady spend, bursts, or lowest cost per job? | Budget owner |
Walkthrough: measure, don't guess
You get the numbers by running the job once on a workstation or a test VM:
# Peak memory and CPU time for one unit of work (Linux)
/usr/bin/time -v python simulate.py --paths 100000 2> run.log
grep -E "Maximum resident|Elapsed|Percent of CPU" run.log
# Percent of CPU this job got: 392% -> about 4 cores busy
# Elapsed (wall clock) time: 34:51 -> about 35 min per unit
# Maximum resident set size (kbytes): 6123400 -> about 5.8 GiB peak
# If a GPU is involved, sample its memory while the job runs
nvidia-smi --query-gpu=name,memory.used,utilization.gpu --format=csv -l 5
Also check what your organisation already enforces. A location policy turns a preference into a hard constraint:
# Is there an org policy restricting where resources may be created?
gcloud org-policies describe gcp.resourceLocations --project=my-project
# If allowedValues lists only in:eu-locations, the data_location field is now HARD
Gotcha: measure the p95, not the average. A job that usually takes 40 minutes but sometimes takes 75 will break a 60-minute limit on a bad night.
The two splits that shrink the shortlist fastest
Tightly coupled vs embarrassingly parallel. Embarrassingly parallel units never talk to each other: Monte Carlo paths, rendering frames, resizing images. Tightly coupled units exchange data all the time: an MPI fluid-dynamics solver, or distributed training that syncs gradients. If one slow node holds up everyone, the work is tightly coupled. Tightly coupled work needs VMs placed physically close to each other with fast interconnect. Google Cloud Batch, for example, offers a compact placement option aimed at tasks that talk over MPI. That one answer usually takes the request-driven serverless platforms (Cloud Run, Cloud Run functions, App Engine) off the list.
Stateless vs stateful, together with duration. A stateless unit can be killed and retried somewhere else. A stateful one loses work unless it checkpoints. Duration then meets hard platform limits. As of October 2026, the docs give these:
- A Cloud Run service request can run for at most 60 minutes. The default is 5.
- A Cloud Run job task can run for up to 168 hours (7 days). Tasks that use a GPU are limited to 1 hour.
- An App Engine standard request times out after 10 minutes with automatic scaling, and after 24 hours with basic or manual scaling.
The Monte Carlo profile above (stateless, 35-minute units, parallel) fits a batch-style service. The same model rewritten as a 9-hour stateful run with no checkpoints rules out the 60-minute and 1-hour limits straight away.
Hard constraints vs preferences
Mark every field H (hard: breaking it is illegal, contractual or technically impossible) or P (preference: you can trade it for cost or convenience).
os_and_licensing: windows-server BYOL # H
data_location: EU only (org policy enforced) # H
accelerator: needs >= 80 GB VRAM per GPU # H
team_skills: prefers no Kubernetes # P
cost_model: prefers no commitments # P
Three common hard constraints:
- Licensing. Google's Microsoft licensing guidance says bring-your-own-licence Windows Server must run on dedicated hardware, meaning sole-tenant nodes or Google Cloud VMware Engine. That single line removes most of the catalogue.
- Data residency. It limits you to regions, and not every service or GPU exists in every region. Cloud Run's L4 GPUs, for example, are offered in a handful of regions only.
- GPU type and memory. Cloud Run currently offers the NVIDIA L4 (24 GB) and the RTX PRO 6000 Blackwell (96 GB). If your profile needs a different accelerator, the shortlist moves towards VMs or Kubernetes.
Best practice: filter by the hard constraints first, then score what's left on the preferences. If you mix them up, a cheap option that breaks a licence can come out on top.
Key takeaways
- A profile has twelve fields: CPU, accelerator, memory, coupling, duration, state, latency, scaling, OS and licensing, data location, compliance, team skills and cost model. Every field takes a measured or estimated number, never an adjective.
- Measure with real runs (
/usr/bin/time -v,nvidia-smi) and use p95 durations. - Tightly coupled work needs closely placed VMs and usually rules out request-driven serverless platforms. Embarrassingly parallel work keeps almost everything on the list.
- Duration and state run into dated, documented limits: 60 minutes for a Cloud Run service request, 168 hours for a Cloud Run job task (1 hour with a GPU), 10 minutes for App Engine standard with automatic scaling.
- Tag fields as hard (H) or preference (P), filter on H first, and only then trade off the P fields.