
In a procedural processing model, you explicitly specify each step-by-step operation to transform and load the data. You control the exact operational control flow (read -> filter -> aggregate -> write)
from pyspark.sql import SparkSession
from pyspark.sql.functions import col
spark = SparkSession.builder.appName("ProceduralPipeline").getOrCreate()
# Step 1: Explicitly load raw data
raw_df = spark.read.json("s3://my-bucket/data/orders.json")
# Step 2: Manually filter completed orders
filtered_df = raw_df.filter(col("status") == "COMPLETED")
# Step 3: Explicitly define aggregation logic
aggregated_df = filtered_df.groupBy("customer_id") \
.sum("amount") \
.withColumnRenamed("sum(amount)", "total_spent")
# Step 4: Manually execute write operation to destination
aggregated_df.write.format("delta").mode("overwrite").saveAsTable("customer_totals")In a declarative processing model, you describe what target table or view should exist, and let the system (such as Lakeflow pipelines) automatically figure out optimization, execution order, and resource management.
-- Define the target view/table declaration
CREATE OR REFRESH MATERIALIZED VIEW customer_totals AS
SELECT
customer_id,
SUM(amount) AS total_spent
FROM
STREAM(live.raw_orders)
WHERE
status = 'COMPLETED'
GROUP BY
customer_id;| Aspect | Procedural Processing | Declarative Processing |
| Control | Full control over execution | Execution handled by system |
| Complexity | Can be complex and verbose | Generally simpler and more concise |
| Optimization | Requires manual tuning | System handles optimization |
| Flexibility | High, but requires expertise | Lower, but easier to use |
| Use Cases | Custom pipelines, performance tuning | SQL queries, managed pipelines |