The problem with cron jobs — you find out at 2am
Most teams start the same way. You need a pipeline: pull data with SQL, clean it with Python, load it into a final table. The solution looks obvious — set up a cron job, schedule the scripts, move on.
In production that approach breaks quietly. A script fails and nobody knows. A dependency breaks and the data is left half-processed. The machine restarts and the cron job never comes back. You walk in the next morning to an empty dashboard.
Cron is a scheduler, not an orchestrator. It runs one script at one time, and that is all. It does not know whether the previous script finished or failed. It will not retry. It will not alert anyone. It does not track dependencies.
- ✗ A script fails and no alert goes out
- ✗ No automatic retry
- ✗ Task dependencies are not tracked
- ✗ Logs are scattered, not in one place
- ✗ Partial failures pass silently
- ✗ Scheduling conflicts and race conditions
- ✓ Immediate alert on failure — email, Slack, PagerDuty
- ✓ Configurable retry with backoff
- ✓ Task B runs only after Task A completes
- ✓ Centralized logs and a visual DAG dashboard
- ✓ On a partial failure, only the failed task retries
- ✓ Backfill support — reprocess data for past dates
What a data pipeline is
A data pipeline is an automated workflow that picks data up from a source, processes it, and loads it into a defined destination. Each step does one specific job, and the steps run in a defined order.
Pull raw data from a database, an API, an S3 bucket, a Kafka topic, or any other source. This step defines where the data comes from and how you connect to it.
Handle null values. Remove duplicate rows. Fix invalid formats. Skip this step and the garbage flows downstream and corrupts the analysis.
Turn raw data into a meaningful shape. Aggregations, joins, calculations — daily revenue by city, say, or monthly active users per product category.
Check expected row counts. Validate the schema. Run anomaly detection. If validation fails, stop the pipeline and send an alert. Never load corrupt data silently.
Load the processed data into a warehouse (BigQuery, Snowflake, Redshift), a database, or a dashboard — ready for analysis and reporting.
DAG — what a directed acyclic graph is
When a pipeline has many steps, some of which can run in parallel while others must run in sequence, you use a DAG to define which task runs when.
Directed — every task has a direction. Task A leads to Task B; it never runs backward.
Acyclic — no cycles. Task A → Task B → Task A is not allowed, so there is no infinite loop.
Graph — tasks are the nodes, dependencies are the edges.
┌─────────────────────┐
│ START (Trigger) │
│ Daily @ 2:00 AM │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ extract_raw_sales │ ← Task A: pull raw CSV from S3
└──────────┬──────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ clean_nulls │ │ remove_dupes │ │ fix_formats │ ← Parallel tasks
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
└───────────────┬┘ ─┘
│
▼
┌─────────────────────┐
│ transform_revenue │ ← Aggregate by city and by product
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ validate_output │ ← Row count check, schema validation
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ load_to_warehouse │ ← Load into BigQuery / Redshift
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ notify_team_slack │ ← "Daily report ready" message
└─────────────────────┘
In this DAG the three cleaning steps run in parallel, all at the same time. But transform_revenue does not start until all three cleaning tasks have finished. The orchestrator handles that dependency tracking for you.
If validate_output fails, load_to_warehouse never runs. Corrupt data never reaches the warehouse, and the team gets a Slack alert saying validation failed.
Apache Airflow — Industry Standard Orchestrator
Airbnb built Apache Airflow in 2014 for its own internal data pipelines and open-sourced it in 2016. Today it is the most widely used pipeline orchestration tool in data engineering — Uber, Twitter, Lyft and Flipkart all run on it.
In Airflow you write the DAG as Python code. It ships with a web UI where you can monitor your pipelines, trigger them manually, or retry individual failed tasks.
from airflow import DAG
from airflow.operators.python import PythonOperator
from datetime import datetime, timedelta
# Default settings — har task pe apply honge
default_args = {
'owner': 'data-team',
'retries': 3, # Failure pe 3 baar retry karega
'retry_delay': timedelta(minutes=5), # 5 minute wait karke retry
'email_on_failure': True, # Fail hone pe email
'email': ['data-team@company.com']
}
# Define the DAG
with DAG(
dag_id='daily_sales_pipeline',
default_args=default_args,
schedule_interval='0 2 * * *', # Har raat 2 baje
start_date=datetime(2025, 1, 1),
catchup=False # Ignore past missed runs
) as dag:
# Task 1 — Extract
extract_task = PythonOperator(
task_id='extract_raw_sales',
python_callable=extract_from_s3 # Tumhara Python function
)
# Task 2 — Transform
transform_task = PythonOperator(
task_id='transform_revenue',
python_callable=aggregate_by_city
)
# Task 3 — Load
load_task = PythonOperator(
task_id='load_to_warehouse',
python_callable=load_to_bigquery
)
# Define the dependency - this is what makes it a DAG
extract_task >> transform_task >> load_task
# Extract complete → Transform start → Load start
Airflow is powerful, but the setup is heavy. You need a dedicated server, a Postgres or MySQL database, and a scheduler process running separately. For large teams that cost is worth paying. For small projects it is usually over-engineering.
Prefect — Modern Python-Native Alternative
Prefect is a newer orchestration tool built to address Airflow's complexity. Its core pitch is simple: "It's just Python." There is no separate DAG syntax to learn. You write the Python you already know and add decorators.
from prefect import flow, task
from prefect.tasks import task_input_hash
from datetime import timedelta
# @task decorator — is function ko pipeline task banao
@task(retries=3, retry_delay_seconds=60, cache_key_fn=task_input_hash)
def extract_raw_sales():
# Pull data from S3 or a database
return fetch_data_from_s3("s3://bucket/sales/")
@task
def transform_revenue(raw_data):
# Aggregate revenue by city
return raw_data.groupby("city")["revenue"].sum()
@task
def load_to_warehouse(transformed_data):
# Load into BigQuery
write_to_bigquery(transformed_data, table="sales.daily_revenue")
# @flow decorator - this is your pipeline entry point
@flow(name="Daily Sales Pipeline")
def daily_sales_pipeline():
raw = extract_raw_sales()
aggregated = transform_revenue(raw)
load_to_warehouse(aggregated)
if __name__ == "__main__":
daily_sales_pipeline() # Locally test kar sakte ho directly
Prefect needs no separate configuration file. You write a Python function, add a decorator, and the pipeline is ready. The same code runs locally and in production, and testing is far simpler because these are plain Python functions.
DAG-based orchestration. Heavy setup, rich UI, a huge ecosystem. Best fit for large teams.
Pure Python decorators. Easy local testing, fast setup, cloud UI built-in. Growing adoption.
Built by Spotify. Good for simple dependency-based pipelines. Not as feature-rich as Airflow.
No infrastructure to manage. Tight integration with the cloud provider. Priced per usage.
Manual cron scripts vs a data pipeline — the difference in production
Both approaches work in a simple scenario. The difference shows up once the pipeline gets complex, the data volume grows, or something unexpected fails at 2am.
CRON JOB APPROACH:
─────────────────────────────────────────────────────
step_1.py ✓ step_2.py ✓ step_3.py ✗ [SILENT]
│
└── Script exits with error code 1
No one knows.
step_4, step_5, step_6 — did they run?
Was data partially loaded?
Dashboard empty in the morning.
Manual investigation starts at 9 AM.
AIRFLOW / PREFECT PIPELINE:
─────────────────────────────────────────────────────
Task 1 ✓ Task 2 ✓ Task 3 ✗
│
├── Immediate Slack / Email alert: "Task 3 failed"
├── Retry attempt 1 (after 5 min) ✗
├── Retry attempt 2 (after 5 min) ✗
├── Retry attempt 3 (after 5 min) ✓ ← Fixed itself
│
├── Task 4, 5, 6 resume automatically
└── Full logs available in UI — exact error line
- A data pipeline is an automated workflow that picks data up from a source, cleans it, transforms it, validates it, and loads it into a final destination — in a defined order.
- A DAG (directed acyclic graph) defines the structure of the pipeline. Every step is a task. Task B runs only after Task A completes. No cycles means no infinite loops.
- Cron jobs are schedulers, not orchestrators. They cannot track dependencies, retry, or send alerts. They are the main cause of silent failures in production.
- Apache Airflow is the industry standard — you write DAGs in Python and get a web UI to monitor your pipelines. It is the best choice for large teams and complex workflows.
- Prefect is the modern alternative — pure Python decorators, easy local testing, fast setup. For new projects or smaller teams it is simpler than Airflow.
- The real data engineering skill is not transforming data. It is automating it, monitoring it, handling retries, and making it production-ready. That is what pipelines give you.
Want the full pipeline guide?
Save the reel so you can come back to it later.
Comment PIPELINE, AIRFLOW, ETL, or DATAFLOW on Instagram —
whichever you need, the full detailed guide lands in your DMs.