Loading preparation module...
Initializing deterministic evaluation engine
Distributed data pipelines, ETL orchestration, columnar storage formats, Lakehouse architectures, and streaming ingestion.
Data Engineers & ETL Architects design and maintain distributed data infrastructure. They build resilient batch and real-time streaming pipelines, manage distributed compute clusters (Spark, Flink), optimize columnar storage formats (Parquet, ORC), and maintain Lakehouse table formats (Iceberg, Delta Lake).
| Level | Title | Experience | Core Architectural Responsibility |
|---|---|---|---|
| L1 | Associate Data Engineer | 0-2 yrs | SQL transformations, Airflow DAG creation, and basic PySpark jobs. |
| L2 | Senior Data Engineer | 2-5 yrs | Spark optimization, streaming pipelines, Lakehouse management, and data modeling. |
| L3 | Staff Data Architect | 5-8 yrs | Enterprise Lakehouse architecture, real-time stream processing, and data governance. |
| L4 | Principal Data Systems Fellow | 8+ yrs | Company-wide data infrastructure strategy, custom compute engines, and distributed storage. |
| Region | Entry Tier (L1) | Mid-Senior (L2/L3) | Staff/Principal (L4+) |
|---|---|---|---|
| North America | $100,000 - $130,000 | $145,000 - $205,000 | $220,000 - $340,000+ |
| Europe (EU/UK) | EUR 58,000 - 80,000 | EUR 88,000 - 135,000 | EUR 145,000 - 220,000+ |
| Asia-Pacific / India | INR 11,00,000 - 18,00,000 | INR 24,00,000 - 44,00,000 | INR 55,00,000 - 95,00,000+ |
Understand distributed computing principles, DAG task scheduling, and columnar storage efficiency.
Build an automated pipeline that ingests raw transactional JSON logs, deduplicates records, computes user aggregate metrics using PySpark, and outputs partitioned Parquet tables.
Master event streaming with Kafka, stream processing with Spark Structured Streaming, and ACID Lakehouses.
Construct a Kafka streaming pipeline that processes incoming credit card transactions, computes sliding 5-minute velocity metrics using Spark Structured Streaming with watermarking, and flags anomalous transactions in real time.
This is the classic "Data Skew" problem. Spark partitions data across executors by hashing the join key (hash(key) % num_partitions). If a single key (e.g. NULL, or a massive high-volume merchant ID) accounts for 20% of the dataset, all those records are routed to a single partition/executor task (the "straggler"), causing memory exhaustion and massive runtime imbalance. Solutions: 1) Salting: Append a random suffix (e.g. key + "_" + random(1..N)) to the skewed key on the left table, and replicate the corresponding dimension record N times with suffixes on the right table to distribute the load across N executors. 2) Broadcast Join: If the dimension table is under the broadcast threshold (default 10MB, or tuned higher), broadcast it to all executors, completely eliminating the shuffle stage. 3) Spark 3.0 Adaptive Query Execution (AQE): Enable spark.sql.adaptive.skewJoin.enabled to automatically split skewed partitions at runtime.
Calling rdd.groupByKey() which shuffles all values across the network before aggregating, causing massive OOM failures.
Use reduceByKey() or aggregateByKey(), which performs map-side partial aggregation before shuffling, drastically reducing network I/O.
Data placement and network shuffle boundaries dictate distributed computing performance.
In a sort-merge shuffle join, all records on both sides must be written to disk, sent across the network, and sorted before the join occurs.
from pyspark.sql import functions as F
# 1. Salt skewed dataset by appending random integer 0-9
SALT_BINS = 10
df_skewed_salted = df_large.withColumn(
"salt", F.concat(F.col("skew_key"), F.lit("_"), F.floor(F.rand() * SALT_BINS))
)
# 2. Replicate dimension table across all salt bins
df_dim_exploded = df_small.withColumn(
"salt_array", F.array([F.lit(i) for i in range(SALT_BINS)])
).withColumn("salt_idx", F.explode("salt_array")).withColumn(
"salt", F.concat(F.col("skew_key"), F.lit("_"), F.col("salt_idx"))
)
# 3. Join on salted key to distribute partition load evenly
joined_df = df_skewed_salted.join(df_dim_exploded, on="salt")