Ingesting and processing the data · Topic 2 of 4
Choosing Processing Services and Building Batch Pipelines
Choose Dataflow, Dataproc, Data Fusion, BigQuery, Pub/Sub or Kafka; cleanse data, build batch transforms in Beam and SQL, and import data from new sources.
- 5 min
- Includes a diagram
- Dataflow for new batch and streaming; Dataproc for existing Spark and Hadoop.
- Data Fusion for visual low-code; BigQuery SQL for ELT.
- Pub/Sub for serverless messaging; Managed Service for Apache Kafka to keep Kafka clients.
What it is
Building a pipeline starts with picking the service that fits the code, team and latency. Then you write the cleansing and batch transformation logic and decide how data is acquired and imported, including from sources the platform has never seen before.
How it works
Identifying the services

| Service | Choose it when |
|---|---|
| Dataflow (runs Apache Beam) | New batch or streaming pipelines; serverless with autoscaling; one code base for both modes |
| Dataproc | Existing Apache Spark or Hadoop ecosystem jobs (Hive, Spark SQL, MapReduce) with little change |
| Cloud Data Fusion | Visual, low-code pipelines with many prebuilt connectors |
| BigQuery | SQL transformations where the data already lives (ELT) |
| Pub/Sub | Serverless, global messaging between producers and consumers |
| Managed Service for Apache Kafka | Existing Kafka clients, Kafka Connect or Kafka Streams must keep working |
On Dataproc, keep data in Cloud Storage instead of HDFS. The cluster then holds no state and can be deleted after the job, which is the basis of cheap, job-based clusters.
"Existing Spark code, minimal changes" means Dataproc. "New pipeline, batch and streaming, no cluster management" means Dataflow. Rewriting Spark into Beam is rarely the intended answer.
Data cleansing
| Problem | Fix |
|---|---|
| Duplicate records | Deduplicate on a business key, keep the latest version |
| Bad types (text in a number field) | SAFE_CAST in SQL returns NULL instead of failing |
| Inconsistent values ("uk", "UK ", "U.K.") | Standardise with TRIM, UPPER and mapping tables |
| Records that cannot be parsed | Send to a dead-letter output for review; never drop silently |
| Missing mandatory fields | Reject, default or flag, following an agreed rule |
-- keep the latest version of each order
SELECT * FROM staging.orders
WHERE TRUE
QUALIFY ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY updated_at DESC) = 1;
Batch transformations in Apache Beam
A batch Beam pipeline reads a bounded source, applies transforms and writes the result. The dead-letter pattern uses a tagged side output for rows that fail.
import apache_beam as beam
class ParseOrder(beam.DoFn):
def process(self, line):
try:
order_id, amount, country = line.split(",")
yield {"order_id": order_id, "amount": float(amount),
"country": country.strip().upper()}
except ValueError:
yield beam.pvalue.TaggedOutput("bad", line)
with beam.Pipeline() as p:
rows = (p
| beam.io.ReadFromText("gs://landing/orders/*.csv", skip_header_lines=1)
| beam.ParDo(ParseOrder()).with_outputs("bad", main="good"))
rows.good | beam.io.WriteToBigQuery(
"prod-data:sales.orders",
schema="order_id:STRING,amount:FLOAT,country:STRING",
write_disposition=beam.io.BigQueryDisposition.WRITE_APPEND)
rows.bad | beam.io.WriteToText("gs://landing/dead-letter/orders")
Data acquisition and import
| Situation | Method |
|---|---|
| Files in Cloud Storage, batch | bq load or the LOAD DATA SQL statement |
| Query files without loading | External or BigLake tables |
| Streaming rows from code | BigQuery Storage Write API |
| Messages from Pub/Sub with no transformation | BigQuery subscription |
| Database changes | Datastream |
| SaaS and other-cloud sources on a schedule | BigQuery Data Transfer Service |
bq load --source_format=PARQUET sales.orders "gs://landing/orders/2026-10-16/*.parquet"
Columnar, self-describing formats such as Parquet and Avro load faster than CSV and carry their schema.
Integrating new data sources
Look for a prebuilt path before writing code: a Google-provided Dataflow template (for example JDBC to BigQuery), a Cloud Data Fusion connector, a BigQuery Data Transfer Service connector or a Datastream source. Write custom Beam code only when no connector exists or the logic is unusual.
A worked example
A bank runs 200 nightly Spark jobs on an on-premises Hadoop cluster and adds a new partner who sends daily CSV files. The goal is to move quickly with a small team.
The engineer moves the Spark jobs to Dataproc, changing hdfs:// paths to gs:// paths. The partner files land in Cloud Storage, a Beam pipeline cleans them with a dead-letter output, and results load into BigQuery.
How the exam asks about this
- "Hundreds of existing Spark jobs must move to Google Cloud quickly with minimal code changes." Dataproc, with data in Cloud Storage.
- "Analysts with no coding skills must build pipelines from many SaaS and database sources." Cloud Data Fusion.
- "Malformed records currently crash the pipeline, but they must be kept for investigation." Catch them in the DoFn and write them to a dead-letter output.
What to remember for the exam
- Dataflow for new batch and streaming; Dataproc for existing Spark and Hadoop.
- Data Fusion for visual low-code; BigQuery SQL for ELT.
- Pub/Sub for serverless messaging; Managed Service for Apache Kafka to keep Kafka clients.
- Deduplicate with a business key; use SAFE_CAST and dead-letter outputs instead of failing.
- Prefer prebuilt templates and connectors before custom code.
Storing working data in HDFS on Dataproc ties data to the cluster. Deleting the cluster deletes the data, so use Cloud Storage.
Common mistakes
Rewriting Spark in Beam for a lift-and-shift. The stem's "minimal changes" points to Dataproc.
Dropping bad records. Silent drops hide data loss; write them to a dead-letter location and alert on volume.
Streaming data into BigQuery when a daily load is enough. Batch loads from Cloud Storage are free of ingestion charges and simpler.
Check yourself
Why keep Dataproc job data in Cloud Storage instead of HDFS?
Data in Cloud Storage outlives the cluster, so clusters can be created per job and deleted afterwards without losing data.
Which SQL function converts a value and returns NULL instead of an error when conversion fails?
SAFE_CAST.
Which service keeps existing Kafka producers and consumers working on Google Cloud?
Google Cloud Managed Service for Apache Kafka.
Topic 2 of 4 in Ingesting and processing the data
Test yourself on Ingesting and processing the data
The full Google Cloud Professional Data Engineer question bank has 733 questions, with timed practice exams and an explanation for every answer.
This study guide is independent and is not affiliated with, endorsed by, or sponsored by Google Cloud. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.