intermediate

Dataflow Architecture

8 min readLast updated: 2026-07-01

1. Introduction

The Google Cloud Dataflow Architecture is designed to decouple compute resources from storage and execution state management. It relies on a distributed control plane that orchestrates job execution, and a separate data plane consisting of worker VMs and specialized backend services that execute transforms and store intermediate pipeline states.

2. Why This Concept Exists

Traditional distributed computing frameworks (like early Apache Hadoop or Apache Spark versions) execute data sharding and state management directly on the worker nodes. This architecture creates several bottlenecks in production:

  • Resource Contention: The same worker VMs must process records, perform disk-based shuffle operations, and keep track of aggregation window states, leading to CPU/RAM starvation.
  • Slow Autoscaling: Adding or removing workers requires moving stored data shards between VMs, which is extremely slow and resource-intensive.
  • Lack of Isolation: A memory leak or failure in the processing code can corrupt the internal state database.

Dataflow's decoupled architecture moves data shuffle and streaming state off the worker nodes into dedicated cloud-hosted services, ensuring workers remain stateless and highly responsive to scaling demands.

3. Key Terminology

  • Control Plane: The Dataflow service backend that optimizes the job execution graph, directs workers, and monitors job health.
  • Data Plane: The collection of Compute Engine VM workers executing user code.
  • Dataflow Shuffle Service: A managed, off-worker service that handles the grouping and sorting of keys for batch pipelines.
  • Streaming Engine: A managed, off-worker service that stores and updates state and windowing information for streaming pipelines.
  • Dataflow Runner v2: The modern, unified execution backend that utilizes the Portability Framework to run pipelines in isolated container environments.

4. How It Works

Dataflow distributes tasks using three primary components:

  1. Job Optimizer: When a job is submitted, the control plane optimizes the user's DAG (e.g., fusing adjacent transforms together to avoid network hops).
  2. Externalized Data Plane:
    • For Batch pipelines, grouping steps (GroupByKey, CoGroupByKey) leverage the Dataflow Shuffle Service instead of writing files to local worker disks.
    • For Streaming pipelines, stateful operations use the Streaming Engine to save windowing state, watermarks, and user-defined state to an external high-throughput storage backend.
  3. Stateless Workers: Because shuffle data and streaming states are externalized, Dataflow workers only perform CPU operations (processing, filtering, mapping). If a worker VM crashes or a new worker is added via autoscaling, no state data needs to be copied or redistributed over the network.

5. Visual Diagram

🧠 Dataflow Control Plane (Managed)
Graph Optimization | VM Orchestration | Autoscaling Decisions
💻 Worker VMs (Compute Plane)
Stateless execution of Map/Filter/ParDo transforms:
VM 1
VM 2
VM 3
Workers scale out/in instantly because they hold no state!
🗄️ Decoupled Backend Services
Externalized state and shuffle operations:

Dataflow Shuffle
Batch Group/Sort

Streaming Engine
Streaming State/Window

Offloads CPU/disk load from VMs to GCP backend!

🔁 Workers stream partition chunks and state updates dynamically to/from the Shuffle & Streaming Engine services.

6. Code Example

The following pipeline options configuration shows how to enable the modern architecture options (Runner v2 and Streaming Engine) programmatically:

python
import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptions, GoogleCloudOptions, StandardOptions

def run_architectural_pipeline():
    options = PipelineOptions()
    
    # 1. Configure standard GCP Options
    gcp_options = options.view_as(GoogleCloudOptions)
    gcp_options.project = "my-gcp-project"
    gcp_options.region = "us-central1"
    gcp_options.job_name = "architecture-demo-job"
    gcp_options.staging_location = "gs://my-bucket/staging"
    gcp_options.temp_location = "gs://my-bucket/temp"
    
    # 2. Set Runner to Dataflow
    options.view_as(StandardOptions).runner = "DataflowRunner"
    
    # 3. Enable Runner v2 & Streaming Engine explicitly
    # Note: Modern SDKs enable these by default for streaming jobs.
    options.view_as(StandardOptions).streaming = True
    
    # Set experiments for Runner v2 and Streaming Engine
    gcp_options.experiments = [
        "use_runner_v2",
        "enable_streaming_engine"
    ]
    
    with beam.Pipeline(options=options) as p:
        (p
         | "ReadStream" >> beam.Create([{"sensor": "temp-1", "val": 22.4}])
         | "Format" >> beam.Map(lambda data: f"Sensor: {data['sensor']} -> {data['val']}")
         | "Log" >> beam.Map(print)
        )

if __name__ == "__main__":
    run_architectural_pipeline()

7. Code Explanation

  • StandardOptions.streaming = True switches the pipeline mode from Batch to Streaming.
  • gcp_options.experiments = ["use_runner_v2", "enable_streaming_engine"] activates modern execution features. Runner v2 allows Python code to execute within standardized container environments (SDK Harness), separating customer code execution from the runner VM system processes.
  • enable_streaming_engine shifts windowing and state storage from worker VM RAM/disk to Google Cloud's dedicated Streaming Engine backend, reducing VM load and improving performance.

8. Real Production Example

An IoT sensor network generates 100,000 temperature readings per second. A streaming pipeline aggregates these values over 5-minute sliding windows. Without Streaming Engine, worker VMs frequently run out of memory because they must hold 5 minutes of data in local memory. By enabling Streaming Engine, the windowing state is offloaded, reducing the memory footprint of worker VMs, allowing them to remain small (e.g., n1-standard-2) and scale rapidly from 4 to 20 instances.

9. Common Mistakes

  • Disabling Streaming Engine on Large Jobs: Not enabling Streaming Engine for high-throughput streaming jobs, which leads to high local disk usage and memory thrashing on workers.
  • Assuming Shared Disk State: Writing intermediate states to local VM disks (/tmp/...) in custom DoFns, assuming other workers or subsequent steps can read them. Workers are stateless; data must only pass through PCollections.

10. Interview Perspective

  • Question: What is the primary operational difference between executing a pipeline with and without the Streaming Engine?
  • Answer: Without Streaming Engine, worker VMs host the state database (typically using local SSDs and RAM). During autoscaling, states must be split, shuffled, and copied to new VMs. With Streaming Engine, state database management is externalized. Worker VMs simply make network calls to fetch and update state keys, making autoscaling almost instantaneous.
  • Question: Why is Runner v2 critical for modern Apache Beam pipelines?
  • Answer: Runner v2 uses containerized SDK harnesses based on Docker. This separates the VM's OS and framework libraries from the user's Python packages, solving dependency version conflicts and standardizing pipeline execution across languages.

11. Best Practices

  • Always enable Runner v2 (use_runner_v2) to utilize the latest performance upgrades, container environments, and debugging features.
  • Always enable Streaming Engine for streaming pipelines to decouple state storage, resulting in smoother autoscaling and cheaper VM costs.
  • Maintain regional consistency: ensure your GCS bucket, Dataflow workers, and Streaming Engine end points are located in the same GCP region to prevent high egress costs.

12. Summary

  • Dataflow decouples the Control Plane from the Data Plane.
  • The Shuffle Service externalizes batch groupings to improve speed.
  • Streaming Engine externalizes streaming states to improve scaling flexibility.
  • Runner v2 provides containerized execution for better portability.

13. Interactive Challenges

Challenge 1: Enable Streaming Engine (Beginner)

Configure the pipeline options to enable Streaming Engine for a streaming pipeline.

Challenge 2: Multi-Experiment Architect Configuration (Intermediate)

Write a Python code snippet that sets up PipelineOptions to run a batch job using Dataflow Runner, explicitly activating Runner v2 (use_runner_v2) and the externalized batch shuffle service (use_portable_shuffle / default shuffle service optimization flags).

Challenge 3: Advanced Pipeline Initialization (Advanced)

Write a Python function init_production_pipeline_options(project, region, bucket) that configures and returns PipelineOptions matching GCP production standards: runs on Dataflow, enables streaming mode, activates Runner v2, enables Streaming Engine, sets standard staging/temp GCS locations under the provided bucket, and limits the VM network tag to "secure-data-subnet".

14. Related Content

Advertisement
AdSense Slot #000001Leaderboard Banner (728x90)