DEV Community

Cover image for Google Cloud Professional Data Engineer (PDE) Certification: Full Prep Roadmap
Gowtham Potureddi
Gowtham Potureddi

Posted on

Google Cloud Professional Data Engineer (PDE) Certification: Full Prep Roadmap

The gcp data engineering certification — officially the Google Cloud Professional Data Engineer, or PDE — is the credential that says you can look at a vague business requirement and pick the right managed service under a cost, latency, or operational-overhead constraint, without reaching for the one you happen to know best. That is the entire skill the exam measures, and it is also the skill that makes you useful the day after you pass: the exam is not a trivia quiz about bq flags, it is two hours of "here is a scenario, here are four services that would all technically work, choose the one that is cheapest / fastest / least operational burden." Miss the constraint and every answer looks correct; read the constraint and three of the four answers eliminate themselves.

This roadmap is the guide you wished existed the first time you opened the exam blueprint and saw five domains, forty-plus services, and no clear order to study them in. It walks the whole professional data engineer exam end to end: the exam facts (format, cost, validity, how questions are written), the five weighted domains and what each one actually tests, a concrete six-to-eight-week study plan you can start on Monday, and a service-selection reflex for every decision the exam throws at you — Pub/Sub versus Dataflow versus Dataproc for ingestion, the BigQuery / Bigtable / Spanner / Cloud Storage / Firestore storage decision tree, BigQuery cost control, and the orchestration and security questions that decide the "maintain and automate" domain. Each domain pairs a teaching block with a worked exam scenario — the four answer choices, the elimination trace, the correct answer, and a concept-by-concept breakdown of why it is correct.

PipeCode blog header for the Google Cloud Professional Data Engineer certification — bold white headline 'GCP Data Engineer Cert' over a hero composition of four exam-domain glyph medallions (design/ingest, store, analyze, operate) arranged on a wheel around a central purple certificate seal, on a dark gradient.

When you want hands-on reps alongside the reading, drill the SQL practice library →, rehearse pipeline design on the ETL practice library →, and sharpen the real-time axis with the streaming practice library →.


On this page


1. What the PDE certification is — and how to read the exam blueprint

The exam measures service selection under a constraint, not memorised syntax

The one-sentence framing that changes how you study: the Professional Data Engineer exam is a two-hour, roughly fifty-question test where nearly every question is a scenario with a hidden constraint — cost, latency, operational overhead, or governance — and your job is to pick the one managed service or configuration that satisfies that constraint, not the one that would merely work. Almost every wrong answer on the exam is a service that would function — it is just more expensive, higher-latency, or more operationally burdensome than the intended answer. That is why rote memorisation of gcloud flags fails and why building a service-selection reflex succeeds.

The exam facts you need before you book.

  • Format. ~50 questions, mix of multiple-choice (one answer) and multiple-select (choose two or three). Two hours. Delivered at a test centre or via online proctoring.
  • Cost. ~$200 USD (plus tax). A retake costs the same; there is a mandatory waiting period after a fail.
  • Validity. The certification is valid for two years; you recertify by re-taking the current exam before it expires.
  • Passing score. Google does not publish a numeric passing score and does not give you a percentage — you get a pass/fail result. Treat "consistently ~80%+ on quality practice exams" as your readiness bar, because the practice-question difficulty is your only calibration signal.
  • Prerequisites. None required, but Google recommends 3+ years of industry experience including 1+ year on Google Cloud. In practice, a data engineer with 1–2 years of hands-on GCP and a disciplined study plan passes comfortably.

The five domains and their weights. The blueprint splits the exam into five sections; the weights are what tell you where to spend your hours.

  • Designing data processing systems (~22%). Choosing architectures, storage, and processing frameworks; migration and modernisation; reliability and fault tolerance.
  • Ingesting and processing the data (~25%). The single biggest domain. Streaming vs batch, Pub/Sub, Dataflow (Apache Beam), Dataproc (Spark/Hadoop), Data Fusion, windowing and late data.
  • Storing the data (~20%). BigQuery, Bigtable, Spanner, Cloud SQL, Cloud Storage, Firestore — matching the store to access pattern, latency, and consistency.
  • Preparing and using data for analysis (~15%). BigQuery analytics, Looker, Dataform, BigQuery ML, materialized views, governance.
  • Maintaining and automating data workloads (~18%). Orchestration (Composer/Workflows), monitoring, autoscaling, cost optimisation, IAM and security.

How PDE questions are written — the keyword tells. Learn to spot the constraint keyword because it is the answer key hiding in plain sight.

  • "Most cost-effective" → the answer trades some latency or convenience for lower spend (serverless, autoscaling to zero, partitioning to scan fewer bytes).
  • "Least operational overhead / fully managed" → prefer the serverless option (Dataflow over self-managed Spark, BigQuery over a self-run warehouse, Workflows over a Composer cluster for simple chains).
  • "Real-time / lowest latency" → streaming path (Pub/Sub + Dataflow, Bigtable for reads), never a nightly batch.
  • "Minimal code / no infrastructure to manage" → a template or a managed connector (Dataflow templates, Data Fusion, BigQuery Data Transfer Service).
  • "Global / strong consistency" → Spanner, not BigQuery and not Bigtable.

What separates a pass from a fail.

  • Can you name the constraint keyword in every scenario before you look at the answers? — the single highest-leverage habit.
  • Do you know the latency and consistency profile of each storage service cold? — required.
  • Can you eliminate two wrong answers immediately and then decide between the last two on cost vs ops overhead? — the technique that wins the close calls.

Worked example — the six-to-eight-week study roadmap

Detailed explanation. The most useful artifact for this exam is a week-by-week plan that front-loads the two biggest domains (ingest/process and store, ~45% combined) and leaves the last week for full-length practice exams and gap-closing. Build the plan around doing, not reading: for every service, spin up a free-tier or trial resource and run one end-to-end job, because the scenarios are written by people who have watched a Dataflow job autoscale and a BigQuery query bill you for a full-table scan.

  • Weeks 1–2. Ingest & process (Pub/Sub, Dataflow windowing, Dataproc). Build one streaming pipeline and one batch job.
  • Weeks 3–4. Storage (BigQuery deep-dive, Bigtable schema design, Spanner vs Cloud SQL). Load data; run partitioned/clustered queries; watch the bytes-scanned meter.
  • Week 5. Analyze (BigQuery SQL, Dataform, Looker, BQML) + governance (IAM, authorized views, Dataplex, DLP).
  • Week 6. Maintain & automate (Composer, Workflows, Monitoring, cost controls, CMEK/VPC-SC).
  • Weeks 7–8 (buffer). Two or three full-length timed practice exams; review every wrong answer until you can articulate why the right answer beat the runner-up.

Question. You have 6 weeks and ~8 hours/week. How should you allocate study time across the five domains to maximise expected score?

Input.

Domain Exam weight Suggested share of hours Why
Ingesting & processing ~25% ~28% Biggest domain; most services; hardest scenarios
Storing the data ~20% ~22% Storage decision tree is high-frequency
Designing systems ~22% ~20% Cross-cutting; reinforced by the other domains
Maintain & automate ~18% ~18% Orchestration + security + cost
Prepare & analyze ~15% ~12% Smallest; mostly BigQuery you already touch

Code.

# A weekly cadence that has worked for busy engineers
Mon–Wed : read the domain's exam-guide bullet points + official docs for 2 services
Thu     : hands-on — build ONE thing (a pipeline, a table, a job) end to end
Fri      : 15–20 practice questions on that domain; log every miss with the reason
Weekend : re-attempt only the missed questions; write the one-line rule you got wrong

# Readiness bar before booking:
#   - >= 80% on two different full-length practice exams
#   - you can state the constraint keyword -> service mapping from memory
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Multiply each domain weight by total hours (48) to get a baseline: ingest 12h, design 10.5h, store 9.6h, maintain 8.6h, analyze 7.2h.
  2. Shift ~2h from analyze (you already use BigQuery daily) into ingest/store (the highest-variance domains).
  3. Reserve weeks 7–8 entirely for timed exams — no new material — because exam stamina and elimination speed are themselves skills.
  4. After each practice exam, sort misses by domain; the domain with the most misses gets the next week's Thursday hands-on session.

Output:

Week Focus Deliverable
1–2 Ingest & process 1 streaming + 1 batch pipeline built
3–4 Storage Partitioned/clustered BQ + Bigtable schema
5 Analyze + governance Dataform DAG + authorized view
6 Maintain & automate Composer DAG + monitoring alert
7–8 Timed practice ≥80% on 2 full exams

Why this works — concept by concept:

  • Weight-proportional allocation — spending hours in proportion to domain weight maximises expected marks per hour, then a small shift toward high-variance domains (ingest, store) reduces the chance of a catastrophic section.
  • Build one thing per domain — the scenarios are written from operational experience; a single end-to-end job teaches you the failure modes (autoscaling, bytes scanned, hotspotting) that trivia cannot.
  • Miss-logging — recording why you missed a question converts a wrong answer into a durable rule ("BigQuery is never the answer for a 10 ms single-row lookup"), which is exactly the reflex the exam rewards.
  • Timed dress rehearsals — the last two weeks build stamina and elimination speed, the two things that decide close questions under a ticking clock.
  • Cost — the plan is ~48 study hours; the exam is $200 and two years valid, so the expected cost per year of credential is modest relative to the salary signal it carries.

The constraint-keyword drill — reading a PDE question before you read the answers

Detailed explanation. The single most transferable exam skill is extracting the constraint from a question stem before your eyes touch the four options, because the options are engineered to all look plausible. Every PDE stem hides its answer in one of a small number of constraint families — latency, cost, operational overhead, consistency, or governance — and once you can name the family, three options usually collapse. Practise this as a mechanical drill: read the stem, underline the constraint clause (often the last sentence), map it to a service class, then read the options and eliminate anything that violates the constraint.

  • Latency words — "real-time", "sub-second", "lowest latency", "immediately" → streaming path or a low-latency store (Pub/Sub+Dataflow, Bigtable, BI Engine).
  • Cost words — "most cost-effective", "minimise cost", "cheapest" → serverless / autoscale-to-zero / scan-fewer-bytes (partitioning, storage classes, on-demand slots).
  • Ops words — "least operational overhead", "fully managed", "no infrastructure to manage" → the serverless option over the cluster (Dataflow > Dataproc, Workflows > Composer).
  • Consistency words — "globally consistent", "strong consistency", "ACID across regions" → Spanner.
  • Governance words — "without exposing PII", "restrict access", "must not copy data" → authorized views / column-level security / VPC-SC.

Question. For each stem, name the constraint family and the service class it points to.

Input.

Question stem (last clause) Constraint family Service class
"…with the least operational overhead." operational overhead serverless
"…the most cost-effective storage for data older than 1 year." cost GCS Coldline/Archive
"…serve single-row reads in under 10 ms at 1M writes/sec." latency + scale Bigtable
"…globally consistent financial transactions." consistency Spanner
"…analysts must not see PII columns." governance column-level security

Code.

# The 4-step drill, applied to every question:
1. READ the last sentence first          -> find the constraint clause
2. NAME the constraint family            -> latency|cost|ops|consistency|governance
3. MAP to a service class                -> (see table above)
4. ELIMINATE options that violate it     -> usually 2 die immediately; decide the last 2
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Take stem 3: the last clause is "under 10 ms at 1M writes/sec" → constraint family = latency + write-scale.
  2. Map: single-digit-ms point reads at massive write volume = Bigtable's exact profile.
  3. Read the options: any that name BigQuery (analytical, seconds) or Cloud SQL (won't scale to 1M/sec) violate the constraint → eliminate.
  4. The surviving option that names Bigtable with a well-distributed row key is the answer.

Output:

Stem Named constraint Winning service
least ops overhead operational overhead serverless (Dataflow/Workflows)
storage > 1 year cost GCS Coldline/Archive
10 ms @ 1M/sec latency + scale Bigtable
global txn consistency Spanner
hide PII governance column-level security

Rule of thumb. If you cannot name the constraint family in one word, re-read the stem — you are not ready to look at the options yet.


2. Design & ingest — Dataflow, Pub/Sub, Dataproc

The ingestion domain is 25% of the exam and hinges on one decision: streaming vs batch, and which managed engine fits

Iconographic ingestion diagram — a Pub/Sub buffer feeding a Dataflow streaming pipeline with a windowing/watermark glyph, a parallel Dataproc Spark lane for batch, and a dead-letter branch, all landing in BigQuery.

The invariant to burn in: on GCP, real-time ingestion is almost always Pub/Sub as the buffer feeding Dataflow as the processor; batch is either Dataflow (if you are writing new pipelines) or Dataproc (if you are lifting existing Spark/Hadoop); and the exam picks between them on "is there existing Spark code," "do you want serverless/no-ops," and "is it streaming." Every ingestion scenario is a variation on that sentence.

The core services and when each wins.

  • Pub/Sub. The global, serverless message bus. It is the ingestion buffer — it decouples producers from consumers, absorbs spikes, and guarantees at-least-once (with an exactly-once option). If the scenario says "ingest millions of events per second from globally distributed sources," Pub/Sub is in the answer. It is not a processor and not a store.
  • Dataflow. Managed Apache Beam. One programming model for both streaming and batch, fully serverless with autoscaling. This is the default answer for new pipelines and for anything needing windowing, watermarks, and late-data handling. "Least operational overhead + streaming transform" → Dataflow.
  • Dataproc. Managed Spark/Hadoop/Presto clusters. The answer when there is existing Spark or Hadoop code to migrate ("lift and shift") or when a team's skillset is Spark. It has clusters to size and (unless you use serverless Dataproc) more ops than Dataflow.
  • Data Fusion / Dataflow templates / Data Transfer Service. The "minimal code / no-code" answers — visual ETL (Data Fusion), pre-built jobs (templates), and scheduled SaaS/warehouse loads (DTS).

Windowing and watermarks — the concept the exam loves. Streaming data arrives out of order and late. Beam/Dataflow groups unbounded data into windows (tumbling/fixed, sliding/hopping, session), tracks progress with a watermark (the system's estimate of "we have probably seen all events up to time T"), and decides what to do with late data via triggers and allowed lateness. If a question describes "events arrive up to 10 minutes late and we need correct hourly aggregates," the answer involves Dataflow windowing with allowed lateness — not a cron batch job.

Common trap answers to pre-empt.

  • Dataproc for greenfield streaming — wrong; new streaming is Dataflow. Dataproc's streaming story is weaker and higher-ops.
  • Cloud Composer as an ingestion tool — wrong; Composer orchestrates jobs, it does not move event data.
  • Loading straight to BigQuery with no buffer for a spiky real-time source — risky; Pub/Sub absorbs the spikes and provides replay.
  • Dataflow when the requirement is "reuse our existing PySpark" — Dataproc is the lift-and-shift answer.

Dataflow windowing — a worked teaching example

Detailed explanation. Consider an IoT fleet publishing temperature readings to Pub/Sub. You need per-device average temperature every 5 minutes, correct even though some devices buffer offline and flush readings up to 10 minutes late. This is the canonical "fixed window + watermark + allowed lateness" pattern, and the exam expects you to recognise it instantly.

Question. Which processing configuration produces correct 5-minute per-device averages when readings can arrive up to 10 minutes late?

Input.

Requirement Value
Source Pub/Sub topic device-readings
Aggregation avg temperature per device_id, per 5 min
Lateness events up to 10 min late
Correctness late events must update the window result

Code.

# Apache Beam (Dataflow) — fixed 5-min windows, 10-min allowed lateness
import apache_beam as beam
from apache_beam.transforms import window
from apache_beam.transforms.trigger import AfterWatermark, AfterProcessingTime, AccumulationMode

(
    p
    | "ReadPubSub" >> beam.io.ReadFromPubSub(topic="projects/x/topics/device-readings")
    | "Parse" >> beam.Map(parse_reading)                      # -> (device_id, (temp, event_ts))
    | "Window" >> beam.WindowInto(
        window.FixedWindows(5 * 60),                          # 5-minute tumbling windows
        trigger=AfterWatermark(late=AfterProcessingTime(60)), # fire on watermark, re-fire on late data
        allowed_lateness=10 * 60,                             # accept events up to 10 min late
        accumulation_mode=AccumulationMode.ACCUMULATING,      # late data updates the running result
      )
    | "KeyByDevice" >> beam.Map(lambda r: (r["device_id"], r["temp"]))
    | "AvgPerDevice" >> beam.combiners.Mean.PerKey()
    | "ToBigQuery" >> beam.io.WriteToBigQuery("proj.ds.device_avg_5m")
)
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Pub/Sub delivers readings; Dataflow assigns each to the 5-minute window its event_ts falls in — not its arrival time.
  2. The watermark advances as time passes; when it crosses a window's end, AfterWatermark fires and emits the average computed so far.
  3. A device that was offline flushes readings 8 minutes late; because allowed_lateness=10min, those readings still land in their original window.
  4. The late trigger re-fires and, because the mode is ACCUMULATING, emits an updated average for that window that includes the late readings.
  5. BigQuery receives a corrected row for the affected window.

Output:

device_id window_start avg_temp note
dev-17 10:00 21.4 on-time result
dev-17 10:00 21.9 corrected after late flush

Why this works — concept by concept:

  • Event-time windowing — grouping by event_ts (not arrival time) is what makes the 5-minute averages meaningful; processing-time windows would smear late readings into the wrong bucket.
  • Watermark — Dataflow's estimate of completeness lets it emit a result promptly while still leaving the window open for a bounded lateness period.
  • Allowed lateness + accumulating mode — together they guarantee that a device flushing 8 minutes late updates the correct window instead of being dropped or double-counted.
  • Pub/Sub buffer — decouples the fleet from the pipeline so an ingestion spike or a pipeline restart never loses readings (replay from the subscription).
  • Cost — Dataflow autoscales workers to the backlog and scales down when idle, so you pay for throughput, not a fixed cluster; the whole path is serverless.

Pub/Sub delivery semantics, ordering & dead-letter — a worked teaching example

Detailed explanation. The exam probes whether you understand what Pub/Sub guarantees and how you make it reliable: default delivery is at-least-once (a message can be redelivered, so consumers must be idempotent), ordering is only preserved when you set an ordering key (and publish to a region), and messages that repeatedly fail processing should be routed to a dead-letter topic after a max delivery attempts threshold instead of being redelivered forever. Exactly-once delivery is available as an opt-in within a region. Recognising which knob a scenario needs — idempotency, ordering key, dead-letter, or exactly-once — is the tell.

  • At-least-once (default). Duplicates possible → make the sink idempotent (dedupe on a message id / business key).
  • Ordering key. Same-key messages delivered in publish order; unrelated keys stay parallel for throughput.
  • Dead-letter topic. After N failed deliveries, move the message aside so a poison message cannot block the subscription.
  • Exactly-once (opt-in, regional). Removes duplicates within the region at some throughput cost.

Question. A payments stream must process each event once, preserve per-account order, and never let one malformed event block the subscription. Configure Pub/Sub.

Input.

Requirement Pub/Sub feature
Per-account ordering ordering key = account_id
No duplicate side effects idempotent sink (or exactly-once)
Poison message isolation dead-letter topic + max delivery attempts
Replay after incident subscription retention / seek

Code.

# Subscription config (conceptual)
ordering_key           = "account_id"          # per-account FIFO
enable_exactly_once    = true                   # regional exactly-once delivery
dead_letter_topic      = "payments-dlq"
max_delivery_attempts  = 5                       # after 5 fails -> DLQ
retain_acked_messages  = true                    # allow seek/replay
# Consumer still dedupes on event_id as defense-in-depth (at-least-once mindset)
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Publisher sets ordering_key = account_id, so all events for one account are delivered in publish order while different accounts stay parallel for throughput.
  2. The subscription enables exactly-once within the region; the consumer additionally dedupes on event_id so a cross-region or config edge case still cannot double-charge.
  3. A malformed event fails processing; after 5 delivery attempts Pub/Sub moves it to payments-dlq instead of redelivering forever — the subscription keeps flowing.
  4. During an incident, retained messages allow a seek/replay to reprocess a time window.

Output:

Concern Result
Ordering per-account FIFO preserved
Duplicates removed (exactly-once + idempotent sink)
Poison message isolated in DLQ after 5 tries
Recovery replay via retention/seek

Rule of thumb. Treat Pub/Sub as at-least-once by default and design idempotent sinks; reach for ordering keys, dead-letter topics, and exactly-once only when the scenario explicitly demands them.

Exam scenario on ingestion

You are asked to design ingestion+processing for a globally distributed clickstream: millions of events/second, need per-session aggregates with late events tolerated, minimal operational overhead, and results in BigQuery for analysts.

Solution Using Pub/Sub + Dataflow session windows into BigQuery

Answer choices (as the exam would present them).

  • A. Cloud Scheduler triggers an hourly Dataproc Spark batch job reading from Cloud Storage.
  • B. Pub/Sub → Dataflow streaming pipeline with session windows and allowed lateness → BigQuery.
  • C. App writes directly to BigQuery via the streaming API with no buffer.
  • D. Cloud Composer DAG polls the source every 5 minutes and loads BigQuery.

Code.

Elimination:
A  batch + Dataproc  -> not real-time, has a cluster to manage      [reject: latency + ops]
C  direct-to-BQ, no buffer -> can't absorb spikes, no replay/late   [reject: reliability]
D  Composer polling  -> Composer orchestrates, it doesn't stream    [reject: wrong tool]
B  Pub/Sub + Dataflow session windows -> serverless, late-tolerant  [ACCEPT]
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Constraint keywords: "millions/sec + global" → Pub/Sub; "per-session + late tolerated" → session windows + allowed lateness; "minimal operational overhead" → serverless Dataflow, not Dataproc clusters.
  2. A is batch (fails real-time) and adds a cluster (fails ops overhead) — eliminate.
  3. C removes the buffer, so a spike or restart drops events and there is no replay — eliminate on reliability.
  4. D uses Composer as if it were an ingestion engine — category error; Composer schedules, Dataflow processes — eliminate.
  5. B satisfies every constraint: Pub/Sub buffers globally, Dataflow session-windows the events with lateness, BigQuery serves analysts, and nothing has servers to manage.

Output:

Constraint Winner
Real-time, millions/sec, global Pub/Sub
Per-session + late data Dataflow session windows
Minimal ops Serverless (no clusters)
Analyst-queryable BigQuery

Why this works — concept by concept:

  • Buffer-then-process — Pub/Sub in front of Dataflow is the canonical GCP streaming shape; it decouples producers, absorbs spikes, and enables replay.
  • Session windows — the exam's cue for "per-session" is literally the Beam Sessions window with a gap duration; recognising the keyword maps straight to the API.
  • Serverless beats clusters on ops-overhead questions — when the constraint is "minimal operational overhead," Dataflow's no-cluster model beats Dataproc every time.
  • Cost — pay-per-throughput autoscaling on Dataflow and per-message Pub/Sub pricing, with no idle cluster cost, is also the most cost-effective steady-state design.

Streaming
Topic — streaming
Streaming ingestion and windowing problems

Practice →

ETL Topic — etl Pipeline design and ingestion problems

Practice →


3. Store the data — BigQuery, Bigtable, Spanner, Cloud Storage

20% of the exam is one decision tree: match the store to access pattern, latency, and consistency

Iconographic storage decision-tree diagram — a central 'pick the store' node branching to BigQuery (analytics), Bigtable (10 ms NoSQL), Spanner (global relational), Cloud Storage (object) and Firestore (document), each with its defining constraint chip.

The invariant: there is one right store per access pattern, and the exam tests whether you can read the access pattern off the scenario — analytical scans over huge tables go to BigQuery, single-row low-latency lookups at massive write volume go to Bigtable, globally-consistent transactional SQL goes to Spanner, objects and data-lake files go to Cloud Storage, and semi-structured document/mobile data goes to Firestore. Pick the wrong one and the scenario's latency or cost requirement is violated.

The decision tree, memorised.

  • BigQuery — serverless, columnar, petabyte-scale analytics warehouse. Best for ad-hoc SQL, aggregations, and BI over large tables. Not for low-latency single-row lookups (it scans; queries are seconds, not milliseconds) and not an OLTP store.
  • Bigtable — wide-column NoSQL for high-throughput, low-latency (single-digit ms) key lookups at massive scale (time-series, IoT, ad-tech, personalisation). You design a single row key; there are no joins and no secondary indexes. If the scenario says "1M writes/sec and 10 ms reads," it is Bigtable.
  • Spanner — horizontally-scalable, globally-distributed, strongly-consistent relational SQL with 99.999% SLA. The answer for a global transactional system that must not lose consistency (financial ledgers, global inventory). More expensive; only pick it when "global + strong consistency + relational" all appear.
  • Cloud SQL — managed MySQL/PostgreSQL/SQL Server for regional OLTP at moderate scale. The answer when the scenario says "existing MySQL app, lift to managed, no global requirement."
  • Cloud Storage (GCS) — object storage for the data lake, staging, backups, and archives; storage classes (Standard/Nearline/Coldline/Archive) are the cost lever, and lifecycle rules tier data down automatically.
  • Firestore — serverless document database for mobile/web app state with real-time sync.

BigQuery internals the exam probes.

  • Partitioning (by ingestion time, a date/timestamp column, or an integer range) prunes whole partitions so queries scan fewer bytes — the primary cost lever.
  • Clustering sorts data within partitions by up to four columns so filtered/aggregated queries read less — stacks on top of partitioning.
  • Slots are the unit of compute; on-demand pricing bills per bytes scanned, capacity/editions pricing bills for reserved slots. "Predictable heavy workload → reserved slots; spiky/ad-hoc → on-demand."
  • Storage vs compute are billed separately — long-term storage auto-discounts untouched data; you pay for query compute independently.

Bigtable schema design the exam probes.

  • The row key determines performance. Keys that monotonically increase (timestamps, sequential IDs) create hotspotting — all writes hit one node. Field-promotion and salting distribute load.
  • Bigtable is "tall and narrow" for time-series (one event per row) or "wide" for entities with many attributes; know both.

Common trap answers.

  • BigQuery for a 10 ms single-row lookup — wrong; that is Bigtable (or a cache). BigQuery is analytical, not low-latency point reads.
  • Spanner for analytics scans — wrong and expensive; analytics is BigQuery. Spanner is transactional.
  • Bigtable when you need joins or ad-hoc SQL — wrong; Bigtable has no joins.
  • Cloud SQL for a global, multi-region, strongly-consistent app — wrong; that is Spanner.

Bigtable row-key design — a worked teaching example

Detailed explanation. A sensor platform writes 1,000,000 readings/second and must serve "latest 24h for device X" in under 10 ms. The naive key timestamp hotspots because all writes land at the tail. Promote the device_id ahead of a reversed/plain timestamp so writes spread across devices and a device's readings stay contiguous for fast range scans.

Question. Design the Bigtable row key for 1M writes/sec with 10 ms "recent readings per device" reads.

Input.

Requirement Value
Write rate ~1,000,000 rows/sec
Read pattern recent readings for a given device_id
Latency target < 10 ms p99
Anti-goal avoid hotspotting a single node

Code.

# BAD: monotonically increasing key -> all writes hit the last node (hotspot)
rowkey = f"{event_ts}"                       # 2026-08-14T10:00:00Z...

# GOOD: field-promotion (device first) + timestamp -> writes spread, reads contiguous
rowkey = f"{device_id}#{event_ts}"           # dev-17#2026-08-14T10:00:00Z

# For "latest first" scans, reverse the timestamp so newest sorts to the top:
rowkey = f"{device_id}#{2**63 - epoch_ms}"   # dev-17#<reversed-ts>
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. With key = event_ts, every write in a given millisecond shares a prefix and lands on the same tablet → one node saturates, the rest idle → hotspot.
  2. Prepending device_id spreads writes across as many tablets as there are active devices → the 1M/sec load balances.
  3. Because a device's rows share the device_id# prefix, "recent readings for device X" is a single contiguous range scan → fast.
  4. Reversing the timestamp makes the newest reading sort first, so "latest 24h" reads the top of the range without scanning the whole device history.

Output:

Key design Write distribution Read for one device
event_ts hotspot (1 node) scattered
device_id#event_ts balanced contiguous range
device_id#reversed_ts balanced newest-first, minimal scan

Why this works — concept by concept:

  • Field promotion — putting the high-cardinality device_id first spreads writes across tablets, which is the entire trick to avoiding Bigtable hotspots.
  • Contiguous range reads — a shared key prefix keeps one device's data physically adjacent, turning "recent per device" into a cheap range scan instead of a full-table scan.
  • Reversed timestamp — encoding newest-first lets a "latest N" read stop early, hitting the sub-10 ms target.
  • No joins by design — Bigtable trades SQL joins for predictable single-digit-ms reads at write volumes BigQuery could never serve as point lookups.
  • Cost — Bigtable bills per node-hour and storage; a well-distributed key lets you serve the load on fewer nodes, which is both the performance and the cost win.

BigQuery partitioning & clustering key choice — a worked teaching example

Detailed explanation. Storing analytical data well in BigQuery is mostly one decision: what to partition by and what to cluster by, because those two choices determine how many bytes every future query scans — and bytes scanned is the bill. Partition by the column that queries filter on by time (usually a date/timestamp, giving up to ~4000 daily partitions or ingestion-time partitioning); cluster by the up-to-four columns queries filter or group by next (high-cardinality, frequently-filtered). Get this wrong and either partition pruning never triggers (queries scan everything) or you hit the partition limit.

  • Partition by a date/timestamp column your queries filter on (event_date), or by an integer range, or by ingestion time.
  • Cluster by the next-most-filtered columns (e.g. country, product_id) — order matters (most-selective first).
  • Set partition expiration to auto-drop old partitions and cap storage.
  • Avoid partitioning on a high-cardinality non-date column (you will exceed the partition limit).

Question. A 5-TB events(event_ts, country, product_id, revenue) table is queried as "last 7 days, filter by country, group by product." Choose partition + cluster keys.

Input.

Query predicate Best physical design
WHERE DATE(event_ts) >= … partition by DATE(event_ts)
WHERE country = … cluster key #1 = country
GROUP BY product_id cluster key #2 = product_id
retention 400 days partition expiration = 400d

Code.

CREATE TABLE analytics.events
PARTITION BY DATE(event_ts)
CLUSTER BY country, product_id
OPTIONS(partition_expiration_days = 400) AS
SELECT * FROM analytics.events_raw;

-- This query now prunes to 7 partitions and reads only matching clusters:
SELECT product_id, SUM(revenue) AS rev
FROM analytics.events
WHERE DATE(event_ts) >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
  AND country = 'US'
GROUP BY product_id;
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Partitioning by DATE(event_ts) lets the 7-day filter prune ~393 of 400 partitions before any scan.
  2. Clustering by country first means the country = 'US' filter reads only the US-sorted blocks within those 7 partitions.
  3. Clustering by product_id second co-locates rows for the GROUP BY, cutting the aggregation's read.
  4. partition_expiration_days = 400 auto-drops older partitions, capping storage without a cleanup job.

Output:

Design Bytes scanned (7-day query)
No partition/cluster ~5 TB
Partition only ~90 GB
Partition + cluster (country, product) ~single-digit GB

Rule of thumb. Partition by the time column queries filter on; cluster by the next filters/group columns, most-selective first; never partition by a high-cardinality non-date column.

Cloud Storage classes & lifecycle — a worked teaching example

Detailed explanation. Object storage cost is a frequent "most cost-effective" question, and the lever is the storage class plus lifecycle rules. GCS offers Standard (hot, frequent access), Nearline (~monthly access), Coldline (~quarterly), and Archive (rarely, e.g. compliance retention). Each colder tier has cheaper storage but higher retrieval cost and a minimum storage duration. The exam answer for "reduce cost for aging data" is almost never "delete it manually" or "move it by hand" — it is a lifecycle rule that transitions objects to a colder class by age and optionally deletes them after a retention window, automatically.

  • Standard — active data lake, staging, frequently read.
  • Nearline — backups/data accessed < once a month.
  • Coldline — data accessed a few times a year.
  • Archive — long-term compliance; cheapest storage, highest retrieval latency/cost.

Question. Raw event files are queried heavily for 30 days, occasionally for a year, then kept 7 years for compliance but almost never read. Minimise total storage cost with no manual ops.

Input.

Age of object Access pattern Target class
0–30 days heavy Standard
31–365 days occasional Nearline
1–7 years compliance only Archive
> 7 years none delete

Code.

// GCS lifecycle policy  automatic class transitions + expiry
{
  "rule": [
    {"action": {"type": "SetStorageClass", "storageClass": "NEARLINE"},
     "condition": {"age": 30}},
    {"action": {"type": "SetStorageClass", "storageClass": "ARCHIVE"},
     "condition": {"age": 365}},
    {"action": {"type": "Delete"},
     "condition": {"age": 2555}}
  ]
}
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. New objects land in Standard and serve the heavy 30-day read window at low latency.
  2. At age 30 the lifecycle rule transitions them to Nearline — cheaper storage for the occasional reads that follow.
  3. At age 365 they move to Archive — cheapest storage for the 7-year compliance hold where reads are rare.
  4. At age 2555 days (~7 years) they are deleted automatically — no human ever touches them.

Output:

Window Class Relative storage cost
0–30 d Standard highest
31–365 d Nearline lower
1–7 y Archive lowest
> 7 y deleted zero

Rule of thumb. "Reduce cost for aging data" = a lifecycle rule that tiers down by age; never a manual migration or a cron job.

Exam scenario on storage selection

A fintech needs a globally-distributed ledger: multi-region, strongly consistent, relational schema with transactions, five-nines availability. Analysts separately need to run large ad-hoc SQL aggregations over the ledger history.

Solution Using Spanner for the ledger + BigQuery for analytics

Answer choices.

  • A. Put everything in BigQuery (ledger writes + analytics).
  • B. Put everything in Bigtable.
  • C. Spanner for the transactional ledger; stream/export to BigQuery for analytics.
  • D. Cloud SQL (PostgreSQL) with read replicas in each region.

Code.

Elimination:
A  BigQuery as an OLTP ledger -> not transactional, seconds not ms writes   [reject]
B  Bigtable -> no relational schema, no multi-row transactions/SQL          [reject]
D  Cloud SQL -> regional; replicas are async -> not global strong consistency[reject]
C  Spanner (global, strong, relational) + BigQuery (analytics)              [ACCEPT]
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Constraint keywords: "globally-distributed + strongly consistent + relational + transactions + five-nines" → this is the textbook Spanner definition.
  2. A misuses BigQuery as a transactional store — BigQuery is analytical, not an OLTP ledger — eliminate.
  3. B loses the relational schema and cross-row transactions — eliminate.
  4. D is regional; read replicas are asynchronous, so it cannot guarantee global strong consistency — eliminate.
  5. C uses each service for its purpose: Spanner owns the consistent global ledger; BigQuery owns the heavy analytical scans, fed by Spanner change streams or scheduled export.

Output:

Need Service
Global, strong, relational, txn Spanner
Ad-hoc PB-scale analytics BigQuery
Five-nines availability Spanner SLA

Why this works — concept by concept:

  • Spanner is the only "global + strong + relational" answer — the moment those three words co-occur, Spanner is correct and everything else is a distractor.
  • Separate transactional and analytical stores — OLTP (Spanner) and OLAP (BigQuery) have opposite access patterns; forcing one store to do both violates a latency or cost constraint.
  • Change streams / export bridge the two — you do not query the ledger for analytics; you flow it into BigQuery where scans are cheap and fast.
  • Cost — Spanner is premium per node, so you only run the ledger there and offload the heavy scans to BigQuery's pay-per-bytes model, keeping the expensive service small.

SQL
Topic — optimization
Query and storage optimization problems

Practice →

Design Topic — design Data storage and system design problems

Practice →


4. Prepare & analyze — BigQuery SQL, Dataform, Looker, BQML

The analytics domain rewards knowing BigQuery deeply and when a lighter tool beats a heavier one

Iconographic analytics diagram — a BigQuery core feeding materialized views and BI Engine into Looker dashboards, a Dataform transformation DAG on one side, a BigQuery ML model box on the other, with a governance shield for authorized views and column-level security.

The invariant: BigQuery is the analytics engine, and the exam tests whether you transform in-warehouse (Dataform/scheduled queries), serve efficiently (materialized views, BI Engine, Looker), model with the lightest sufficient tool (BQML before Vertex AI), and govern access without copying data (authorized views, column-level security). The recurring theme is "use the managed, in-warehouse option, and control cost = bytes scanned."

BigQuery analytics features the exam expects.

  • Nested and repeated fields (STRUCT/ARRAY) — BigQuery stores semi-structured data natively; UNNEST flattens repeated fields. Denormalising with nested fields is often preferred over joins for performance.
  • Window functions — ranking, running totals, and lag/lead over partitions; standard SQL, heavily used in analytics scenarios.
  • Materialized views — precomputed, incrementally-refreshed aggregates that BigQuery can auto-route queries to; the answer for "speed up a repeated expensive aggregation with minimal maintenance."
  • BI Engine — an in-memory acceleration layer for sub-second dashboards on BigQuery, the answer for "make Looker/Data Studio dashboards fast."
  • Search indexes / primary+foreign keys (advisory) — newer features that inform the optimiser.

Transformation and modelling.

  • Dataform (or dbt) — SQL-based, version-controlled transformation inside BigQuery, with dependency DAGs and tests. The answer for "manage ELT transformations as code." Scheduled queries cover simpler periodic transforms.
  • BigQuery ML (BQML) — train and serve models with SQL (CREATE MODEL) directly in BigQuery: linear/logistic regression, k-means, time-series (ARIMA_PLUS), boosted trees, and even calls to Vertex AI models. The exam picks BQML when the data is already in BigQuery and the model is standard, and Vertex AI when you need custom training, deep learning, or MLOps at scale.
  • Looker — the governed semantic/BI layer (LookML) for self-serve analytics; the answer for "consistent, governed metrics across the org."

Governance without copying data.

  • Authorized views / authorized datasets — expose a query result to a group without granting access to the underlying tables.
  • Column-level security with policy tags (via Data Catalog/Dataplex) and row-level security restrict fields/rows by principal.
  • Dataplex — governance and a data mesh/lakehouse catalog across GCS + BigQuery; DLP discovers and de-identifies sensitive data.

Common trap answers.

  • Vertex AI for a standard forecast on data already in BigQuery — usually overkill; BQML ARIMA_PLUS is the lighter correct answer.
  • Copying data into a new dataset to restrict access — wrong; authorized views/column-level security expose without copying.
  • A nightly full-table aggregation job when a materialized view would refresh incrementally — wrong on cost and freshness.
  • SELECT * on a wide table — scans every column and blows the bytes-scanned bill; select only needed columns.

BigQuery cost control — a worked teaching example

Detailed explanation. An analyst dashboard reruns the same daily revenue aggregation over a 2-TB events table dozens of times a day, scanning the whole table each time. Partition by date, cluster by country, and back the dashboard with a materialized view so repeated queries scan kilobytes instead of terabytes.

Question. How do you cut the bytes scanned (and therefore cost) for a repeated daily-revenue-by-country dashboard over a 2-TB table?

Input.

Fact Value
Table events — 2 TB, 400 days of data
Query daily revenue by country, last 30 days
Frequency dozens of runs/day
Current full-table scan each run (2 TB)

Code.

-- 1) Partition by day + cluster by country so filters prune + co-locate
CREATE TABLE analytics.events_p
PARTITION BY DATE(event_ts)
CLUSTER BY country AS
SELECT * FROM analytics.events;

-- 2) Materialized view for the exact repeated aggregation (auto-incremental refresh)
CREATE MATERIALIZED VIEW analytics.daily_rev_by_country AS
SELECT DATE(event_ts) AS d, country, SUM(revenue) AS revenue
FROM analytics.events_p
GROUP BY d, country;

-- 3) Dashboard queries the MV, filtered to 30 days -> scans partitions, not 2 TB
SELECT d, country, revenue
FROM analytics.daily_rev_by_country
WHERE d >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY);
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Partitioning by DATE(event_ts) means a 30-day filter prunes ~370 of 400 partitions → the engine reads ~1/13th of the data.
  2. Clustering by country co-locates rows per country so GROUP BY country reads less within each partition.
  3. The materialized view precomputes the daily sums and refreshes incrementally as new data lands, so each dashboard run reads a tiny aggregate, not raw events.
  4. BigQuery can even auto-rewrite a query against the base table to use the MV when it matches.

Output:

Stage Bytes scanned per run
Full-table scan ~2 TB
Partition prune (30/400 days) ~150 GB
+ clustering ~tens of GB
Materialized view ~KB–MB

Why this works — concept by concept:

  • Partitioning prunes — a date filter skips whole partitions, and because BigQuery bills per byte scanned, skipping data is skipping cost.
  • Clustering co-locates — sorting within partitions by the filter/group column reduces the bytes read for those predicates, stacking on partitioning.
  • Materialized views precompute — the repeated aggregation is computed once and refreshed incrementally, so dozens of daily runs read a small aggregate instead of re-scanning raw data.
  • Cost = bytes scanned — every optimisation here is really the same optimisation: read fewer bytes, pay less, return faster.

Nested & repeated fields (UNNEST) — a worked teaching example

Detailed explanation. BigQuery is columnar and stores semi-structured data natively as STRUCT (nested) and ARRAY (repeated) fields, and the exam expects you to know that denormalising with nested/repeated fields is often preferred over joins because it keeps related data co-located and avoids a shuffle. You read repeated fields back into rows with UNNEST. Recognising "one order with many line items" as an ARRAY<STRUCT> — not two joined tables — is the modelling instinct the analytics domain tests.

  • STRUCT groups related columns (an address, a geo point) under one field.
  • ARRAY holds repeated values (tags, line items) without a child table.
  • UNNEST flattens an array into rows for aggregation.
  • Why prefer it — no join/shuffle for the one-to-many; columnar storage still prunes unread fields.

Question. An orders table stores line items as a repeated STRUCT. Compute total revenue per order and per product.

Input.

Field Type
order_id INT64
items ARRAY<STRUCT<product STRING, qty INT64, price NUMERIC>>

Code.

-- Revenue per order: sum the array's line items with a correlated UNNEST
SELECT
  order_id,
  (SELECT SUM(i.qty * i.price) FROM UNNEST(items) AS i) AS order_revenue
FROM analytics.orders;

-- Revenue per product: flatten items to rows, then aggregate
SELECT i.product, SUM(i.qty * i.price) AS product_revenue
FROM analytics.orders, UNNEST(items) AS i
GROUP BY i.product;
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. items is stored inline with each order as a repeated STRUCT — no separate order_items table, so no join is needed.
  2. The correlated UNNEST(items) in the SELECT sums line items within one order, yielding per-order revenue.
  3. The second query cross-joins each order with its flattened items, producing one row per line item.
  4. GROUP BY i.product then aggregates across all orders — all without ever shuffling two tables together.

Output:

Query Sample result
per order order 1001 → 248.50
per product "widget" → 18,420.00

Rule of thumb. Model one-to-many as ARRAY<STRUCT> and read it with UNNEST when the child is always queried with its parent; reach for a join only when the child is independently queried at scale.

BigQuery ML forecast — when BQML beats Vertex AI, a worked teaching example

Detailed explanation. A recurring analytics question is "the data is already in BigQuery and we need a standard model — what's the least-effort path?" The exam answer is BigQuery ML: you train and serve with SQL (CREATE MODEL), no data movement, no separate serving infrastructure. ARIMA_PLUS handles time-series forecasting (with automatic seasonality and holiday effects); LOGISTIC_REG/BOOSTED_TREE_CLASSIFIER handle classification; KMEANS handles clustering. You escalate to Vertex AI only when you need custom/deep-learning architectures, large-scale training, or full MLOps — not for a standard forecast on warehouse data.

Question. Forecast the next 30 days of daily sales per product from a BigQuery sales table, with minimal effort and no data export.

Input.

Fact Value
Data sales(product_id, day, units) already in BigQuery
Task 30-day per-product forecast
Constraint minimal effort, no data movement
Model seasonal time-series

Code.

-- Train a per-product time-series model directly in BigQuery
CREATE OR REPLACE MODEL analytics.sales_arima
OPTIONS(
  model_type='ARIMA_PLUS',
  time_series_timestamp_col='day',
  time_series_data_col='units',
  time_series_id_col='product_id'      -- one model per product, trained together
) AS
SELECT day, units, product_id FROM analytics.sales;

-- Forecast 30 days ahead with prediction intervals
SELECT * FROM ML.FORECAST(
  MODEL analytics.sales_arima,
  STRUCT(30 AS horizon, 0.9 AS confidence_level)
);
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. CREATE MODEL … ARIMA_PLUS trains directly on the BigQuery table — no export, no notebook, no cluster.
  2. time_series_id_col='product_id' fits a separate seasonal model per product in one statement.
  3. ML.FORECAST(... horizon => 30) returns the 30-day forecast with confidence bounds as a normal query result.
  4. The output is queryable/joinable immediately and can back a Looker dashboard — still no data left BigQuery.

Output:

product_id forecast_day forecast_units lower_90 upper_90
p-1 2026-08-15 812 740 884
p-2 2026-08-15 143 121 165

Rule of thumb. Standard model + data already in BigQuery → BQML. Custom/deep-learning/MLOps → Vertex AI. Do not export data to train something BQML already does in SQL.

Exam scenario on analytics + governance

Analysts need self-serve dashboards over a sensitive customer table, but must not see PII columns, and the org wants consistent metric definitions. Minimise cost and avoid duplicating data.

Solution Using authorized views + column-level security + Looker + BI Engine

Answer choices.

  • A. Copy the table into a PII-free dataset for analysts.
  • B. Authorized views + column-level policy tags to hide PII, Looker for governed metrics, BI Engine for speed.
  • C. Grant analysts direct table access and trust them to avoid PII columns.
  • D. Export to spreadsheets nightly with PII removed by a script.

Code.

Elimination:
A  copy data -> duplication, drift, extra cost/governance surface     [reject]
C  direct access -> exposes PII, no governance                        [reject]
D  nightly export -> stale, brittle, ungoverned                       [reject]
B  authorized views + column security + Looker + BI Engine            [ACCEPT]
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Constraints: "must not see PII," "consistent metrics," "minimise cost," "avoid duplicating data."
  2. A duplicates the table — violates "avoid duplicating data" and creates a second thing to secure and keep in sync — eliminate.
  3. C exposes PII outright — fails the security requirement — eliminate.
  4. D is stale and ungoverned — eliminate.
  5. B hides PII columns via policy tags/authorized views (no copy), defines metrics once in Looker (LookML) for consistency, and uses BI Engine for sub-second dashboards.

Output:

Requirement Mechanism
Hide PII, no copy Authorized views + column-level security
Consistent metrics Looker / LookML semantic layer
Fast dashboards BI Engine
Low cost Query in place; no duplication

Why this works — concept by concept:

  • Expose without copying — authorized views and column-level security grant result access while the base table stays locked, eliminating duplication and drift.
  • Semantic layer for consistency — defining metrics once in Looker prevents every analyst reinventing "revenue," which is the governance win the scenario asks for.
  • BI Engine for latency — the in-memory layer is the specific answer to "make dashboards fast" without pre-materialising everything.
  • Cost — querying in place with partition/cluster pruning and MV acceleration beats maintaining a second copy on both storage and compute.

SQL
Topic — window-functions
Analytical SQL and window-function problems

Practice →

Analytics Topic — real-time-analytics Real-time analytics and aggregation problems

Practice →


5. Maintain, automate & the exam-day playbook

The last domain is orchestration, monitoring, cost, and security — plus the test-taking technique that wins close questions

Iconographic operations diagram — a Cloud Composer orchestration DAG with a monitoring gauge, autoscaling arrows on a Dataflow job, an IAM least-privilege shield, and an exam-day elimination funnel narrowing four answer chips to one.

The invariant: once data flows, the exam asks how you schedule it (Composer vs Workflows vs Scheduler), how you keep it healthy and cheap (Monitoring, autoscaling, slot reservations, lifecycle rules), and how you secure it (IAM least privilege, CMEK, VPC Service Controls) — and the correct answer is always the least-operational-overhead option that still meets the reliability and compliance bar.

Orchestration — pick by complexity.

  • Cloud Composer (managed Apache Airflow) — the answer for complex, dependency-rich DAGs with retries, backfills, and a rich operator ecosystem. It runs a cluster, so it has a baseline cost and some ops; worth it for real pipelines.
  • Workflows — serverless orchestration of API/service calls in YAML; the answer for lightweight chaining ("call this, then that") without a Composer cluster.
  • Cloud Scheduler — managed cron; the answer for "trigger a job on a schedule," often paired with Pub/Sub or Workflows.
  • Dataflow / BigQuery scheduled queries cover in-tool scheduling for their own jobs.

Reliability, monitoring, and cost.

  • Cloud Monitoring + Logging + Error Reporting — metrics, dashboards, alerting; the answer for "detect and alert on pipeline failures/latency."
  • Autoscaling — Dataflow scales workers to backlog; the answer for "handle variable load without over-provisioning."
  • BigQuery cost controls — reservations/editions for predictable heavy workloads, on-demand for spiky; custom quotas and maximum_bytes_billed guardrails; partition expiration.
  • Cloud Storage lifecycle — auto-tier to Nearline/Coldline/Archive and delete by age; the answer for "reduce storage cost for aging data."
  • Dead-letter queues + retries + idempotency — the reliability triad for streaming.

Security and compliance.

  • IAM least privilege — grant the narrowest predefined role (or a custom role); service accounts per workload. "Which role?" questions want the least privilege that still works.
  • CMEK (customer-managed encryption keys) — the answer for "we must control the encryption keys."
  • VPC Service Controls — a security perimeter that prevents data exfiltration from services like BigQuery/GCS; the answer for "prevent data leaving the perimeter."
  • Data residency — region/multi-region selection to keep data in a jurisdiction.

The exam-day playbook — how to actually take the test.

  • Read the last sentence first. The constraint (cost / latency / least ops / global) usually lives in the final clause. Name it before reading the options.
  • Eliminate two immediately. There are almost always two answers that are wrong on an obvious axis (batch when it says real-time; a cluster when it says serverless). Cross them out.
  • Decide the last two on the constraint keyword. Between two workable options, the "most cost-effective" or "least operational overhead" phrase is the tiebreaker.
  • Watch for "choose TWO/THREE." Multiple-select questions penalise partial answers; count the required selections.
  • Flag and move on. Do not sink 5 minutes into one question; flag it, bank the easy marks, return with time left.
  • Beware absolute distractors ("always," "never") and services used out of role (Composer moving data, BigQuery serving 10 ms lookups).

Making a flaky pipeline reliable — a worked teaching example

Detailed explanation. A nightly Composer DAG loads BigQuery but fails intermittently on transient errors and no one notices until morning. Add retries with backoff, a Monitoring alert on DAG failure, idempotent loads (write to a date-partitioned table with WRITE_TRUNCATE per partition), and a dead-letter path for bad records — all low-ops, managed features.

Question. How do you make a flaky nightly BigQuery load reliable and observable at least operational cost?

Input.

Symptom Fix lever
Transient task failures retries + exponential backoff
Silent failures Monitoring alert on DAG state
Re-runs double-load data idempotent partition truncate
Bad records abort the load dead-letter table

Code.

# Cloud Composer (Airflow) task with retries + alerting + idempotent load
default_args = {
    "retries": 3,
    "retry_delay": timedelta(minutes=5),
    "retry_exponential_backoff": True,
    "on_failure_callback": alert_cloud_monitoring,   # fire a Monitoring/alerting notification
}

load = BigQueryInsertJobOperator(
    task_id="load_events",
    configuration={"load": {
        "destinationTable": {"projectId": "p", "datasetId": "raw", "tableId": "events$20260814"},
        "writeDisposition": "WRITE_TRUNCATE",   # idempotent: re-run overwrites the partition
        "sourceUris": ["gs://bucket/events/2026-08-14/*.json"],
        "sourceFormat": "NEWLINE_DELIMITED_JSON",
        "maxBadRecords": 0,                       # bad records routed to a dead-letter step
    }},
    default_args=default_args,
)
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. A transient BigQuery/network error now triggers up to 3 retries with exponential backoff instead of failing the run outright.
  2. If all retries fail, on_failure_callback fires a Cloud Monitoring alert — someone is paged instead of discovering it at 9 a.m.
  3. Loading into the date-partition decorator events$20260814 with WRITE_TRUNCATE makes a re-run overwrite only that day's partition, so replays are idempotent (no doubles).
  4. Bad records are routed to a dead-letter table for inspection rather than aborting the whole load.

Output:

Before After
Silent nightly failures Retries + alert on failure
Re-runs double-count Idempotent per-partition truncate
One bad row kills the load Dead-letter isolates bad rows

Why this works — concept by concept:

  • Retries with backoff — most pipeline failures are transient; bounded exponential retries absorb them without human involvement and at no extra service cost.
  • Alert on failure — observability turns a silent failure into a paged incident; Cloud Monitoring is the managed, low-ops way to get there.
  • Idempotent partition loads — writing per-partition with WRITE_TRUNCATE means "run it again" is always safe, which is the core reliability property for batch loads.
  • Dead-letter isolation — quarantining bad records keeps one malformed row from failing the entire batch.
  • Cost — every fix uses managed features (Composer retries, Monitoring alerts, BigQuery partition semantics) so reliability improves with near-zero added operational overhead — exactly what "least operational overhead" questions reward.

IAM least-privilege role selection — a worked teaching example

Detailed explanation. Security questions almost always ask for the least privilege that still works, and the trap answer is a broad primitive role (Owner/Editor) or a project-level grant when a resource-level predefined role would do. GCP's model is: attach the narrowest predefined role to a per-workload service account, at the narrowest resource scope. For "a Dataflow job that reads a Pub/Sub subscription and writes one BigQuery dataset," you do not grant BigQuery Admin on the project — you grant roles/bigquery.dataEditor on that dataset plus roles/pubsub.subscriber on that subscription.

  • Service account per workload — not a shared human account; scoped, auditable, rotatable.
  • Predefined over primitivedataEditor not Editor; dataViewer not Viewer.
  • Resource scope over project scope — grant on the dataset/bucket/subscription, not the whole project.
  • Custom role — only when no predefined role fits.

Question. A Dataflow pipeline reads subscription clicks-sub and writes dataset analytics. Grant the least privilege that works.

Input.

Action needed Narrowest role Scope
Read the subscription roles/pubsub.subscriber subscription clicks-sub
Write the dataset roles/bigquery.dataEditor dataset analytics
Run the job roles/dataflow.worker project (worker SA)
Anti-pattern roles/editor / roles/owner project ❌

Code.

# Per-workload service account, resource-scoped predefined roles:
sa = dataflow-clicks@project.iam

grant roles/pubsub.subscriber   on subscription clicks-sub   to sa
grant roles/bigquery.dataEditor on dataset analytics         to sa
grant roles/dataflow.worker     on project (worker identity) to sa
# NOT: roles/editor on the project  (far more than the job needs)
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Create a dedicated service account for this pipeline so its permissions are isolated and auditable.
  2. Grant pubsub.subscriber only on clicks-sub — the job can read that subscription and nothing else in Pub/Sub.
  3. Grant bigquery.dataEditor only on the analytics dataset — it can write there but cannot touch other datasets.
  4. Grant the dataflow.worker role for the job to run; reject any answer that hands out Editor/Owner.

Output:

Option Verdict
Owner/Editor on project ❌ over-privileged
Resource-scoped predefined roles on a per-workload SA ✅ least privilege

Rule of thumb. "Which role?" questions want the narrowest predefined role at the narrowest scope on a dedicated service account — never a primitive role and never project-wide when resource-scope works.

Exam scenario on orchestration choice

You need to run three dependent steps once a day — export from Cloud SQL, transform in BigQuery, notify a downstream service — with retries and minimal operational overhead. There is no complex DAG, no backfills, no large operator ecosystem needed.

Solution Using Cloud Scheduler + Workflows (not a Composer cluster)

Answer choices.

  • A. Stand up Cloud Composer to run the three steps.
  • B. Cloud Scheduler triggers a serverless Workflow that runs the three steps with retries.
  • C. A Compute Engine VM running cron and bash scripts.
  • D. Chain three separate Cloud Functions with manual timers.

Code.

Elimination:
A  Composer -> runs a cluster (baseline cost + ops) for a 3-step chain   [reject: overkill]
C  VM + cron -> self-managed, patching, no managed retries               [reject: high ops]
D  hand-chained Functions + manual timers -> brittle, no orchestration   [reject]
B  Scheduler + Workflows -> serverless, built-in retries, minimal ops    [ACCEPT]
Enter fullscreen mode Exit fullscreen mode

Step-by-step trace.

  1. Constraint keywords: "three dependent steps," "once a day," "retries," "minimal operational overhead," "no complex DAG."
  2. A (Composer) is the right tool for complex DAGs but runs a managed cluster with baseline cost — overkill for a 3-step chain — eliminate on ops/cost.
  3. C is a self-managed VM (patching, uptime, no managed retries) — the opposite of minimal overhead — eliminate.
  4. D hand-rolls orchestration and timing — brittle and unobservable — eliminate.
  5. B uses Cloud Scheduler (managed cron) to kick a serverless Workflow that sequences the steps with built-in retry/error handling — zero clusters, minimal ops.

Output:

Requirement Winner
Simple daily chain Workflows
Scheduled trigger Cloud Scheduler
Retries, low ops Serverless, managed

Why this works — concept by concept:

  • Right-size the orchestrator — Composer is correct for complex DAGs, but for a short serverless chain, Workflows wins the "minimal operational overhead" tiebreaker because it has no cluster.
  • Managed cron — Cloud Scheduler is the standard, low-ops way to trigger on a schedule and pairs naturally with Workflows/Pub/Sub.
  • Serverless retries — Workflows' built-in error handling gives you reliability without writing or operating retry infrastructure.
  • Cost — no idle cluster; you pay per execution, which is both cheapest and lowest-ops for infrequent, simple pipelines.

ETL
Topic — etl
Orchestration and reliability problems

Practice →

Design
Course — ETL system design
ETL system design for data engineering interviews

Practice →


Cheat sheet — PDE service-selection recipes

Keyword → service lookup (memorise this table).

Scenario keyword Service answer
Real-time ingest, millions/sec, global Pub/Sub (buffer)
Streaming transform, windows, late data, no-ops Dataflow (Beam)
Reuse existing Spark/Hadoop code Dataproc
No-code / visual ETL Data Fusion / Dataflow templates
Ad-hoc SQL analytics at PB scale BigQuery
10 ms single-row reads, 1M writes/sec Bigtable
Global, strongly-consistent relational + txn Spanner
Regional managed MySQL/Postgres OLTP Cloud SQL
Objects, data lake, archive Cloud Storage (+ lifecycle)
Mobile/web document store, real-time sync Firestore
In-warehouse SQL transforms as code Dataform / dbt
Standard model on data already in BQ BigQuery ML
Custom/deep-learning model, MLOps Vertex AI
Governed self-serve metrics Looker
Complex DAG, retries, backfills Cloud Composer
Simple serverless step-chain Workflows
Schedule/cron trigger Cloud Scheduler

BigQuery cost-control checklist.

  • Partition by date/timestamp; cluster by up to 4 filter/group columns.
  • Never SELECT * on wide tables — select only needed columns.
  • Materialized views for repeated aggregations; BI Engine for dashboards.
  • On-demand (per-byte) for spiky/ad-hoc; reservations/editions for steady heavy load.
  • Set maximum_bytes_billed guardrails and partition expiration.

Dataflow vs Dataproc decision line. New pipeline or streaming with windows/no-ops → Dataflow. Existing Spark/Hadoop to migrate or Spark-skilled team → Dataproc (serverless Dataproc if you want less cluster management).

6–8 week study plan recap. Weeks 1–2 ingest/process → 3–4 storage → 5 analyze+governance → 6 maintain/automate → 7–8 timed practice exams to ≥80%.

Exam-day elimination heuristic. Read the last sentence → name the constraint → eliminate the two obviously-wrong options → decide the last two on cost vs operational overhead → flag hard ones and move on.


Frequently asked questions

Is the GCP Professional Data Engineer certification worth it in 2026?

For data engineers working on (or moving to) Google Cloud, yes — it is one of the more respected cloud data credentials and directly signals the service-selection judgment employers pay for. It carries the most weight when paired with hands-on GCP experience; as a pure paper credential with no practical exposure it helps less. The gcp data engineering certification is especially valuable for consultants, those targeting GCP-heavy shops, and engineers wanting a structured reason to learn BigQuery, Dataflow, and the rest of the stack deeply.

How long does it take to prepare for the PDE exam?

For someone with 1–2 years of general data engineering experience and some GCP exposure, a focused 6–8 weeks at ~8 hours/week is a realistic plan. If you are new to Google Cloud specifically, budget 10–12 weeks and spend more of it hands-on. The single best predictor of readiness is scoring consistently ~80%+ on full-length, good-quality practice exams — not hours logged reading.

What's the passing score for the PDE exam?

Google does not publish a numeric passing score and gives you only a pass/fail result — no percentage. Because you cannot calibrate against an official cut line, use quality practice exams as your gauge and aim to clear ~80% comfortably before booking. Focus your final week on understanding why the right answer beats the runner-up on cost or operational overhead.

Do I need to know Apache Beam / Dataflow code for the exam?

You do not have to write production Beam code, but you must understand Dataflow concepts: the unified batch/streaming model, windowing (fixed, sliding, session), watermarks, triggers, and allowed lateness for late data. Scenarios will describe a late-data or per-session requirement and expect you to map it to the right windowing configuration — recognising the pattern matters far more than syntax recall.

PDE vs AWS DEA-C01 vs Azure DP-700 — which should I take?

Take the one that matches your cloud. If your company runs on GCP, the PDE is the highest-ROI choice; on AWS, take the Data Engineer Associate (DEA-C01); on Azure/Fabric, take DP-700. All three test the same underlying judgment — pick the right managed service under a constraint — just with different service names. If you are cloud-agnostic and choosing for breadth, PDE and DEA-C01 are the two most recognised data-engineering-specific exams.

Is the PDE exam multiple choice or hands-on?

It is multiple-choice and multiple-select scenario questions, delivered at a test centre or via online proctoring — there is no live hands-on lab. That said, the questions are written from operational experience, so hands-on practice (building one pipeline, one Bigtable schema, one partitioned BigQuery table) is the most efficient way to answer them correctly, because you will have seen the failure modes the distractors are built around.


Practice on PipeCode

Turn the PDE blueprint into muscle memory

Study guides explain the services. PipeCode drills build the reflex the exam actually tests — reading the constraint, eliminating the two wrong services, and defending the cost-vs-operational-overhead tiebreaker under a clock. Pipecode.ai is Leetcode for Data Engineering — scenario-first practice on SQL, ETL, and streaming tuned to the trade-offs the Professional Data Engineer exam rewards.

Practice SQL problems →
Practice ETL problems →

Top comments (0)