Case study · Data platform
Earthquake Analytics Pipeline
An end-to-end Google Cloud data platform over approximately 500,000 earthquake events from the USGS catalog (2015 to 2025). Infrastructure is provisioned with Terraform, ingestion runs monthly through Kestra into Cloud Storage, transformations happen in dbt, and the warehouse is a BigQuery table partitioned by month and clustered by magnitude category and region. The result is exposed as an interactive Looker Studio dashboard.
At a glance
- Dataset
- Approximately 500,000 earthquake events, magnitude 1.0 and above, 2015 to 2025 (USGS Earthquake Catalog)
- Infrastructure
- Terraform: Cloud Storage bucket, BigQuery dataset, and a service account scoped to GCS and BigQuery
- Orchestration
- Kestra (Docker), monthly batch runs with a backfill entry point from January 2015
- Data lake
- Cloud Storage, raw Parquet written per month
- Warehouse
- BigQuery, partitioned by month and clustered by magnitude category and region
- Modeling
- dbt in three layers: staging, intermediate, and marts, including a fact table and a monthly aggregate
- Geospatial
- Latitude, longitude, and depth carried through to the mart for mapping and regional analysis
- Dashboard
- Looker Studio, embeddable and filterable by magnitude (see below)
Interactive dashboard
Architecture
→ BigQuery (external table, then partitioned and clustered table)
→ dbt (staging, intermediate, marts) → Looker Studio
What I built
- Reproducible infrastructure. Terraform provisions the storage bucket, the BigQuery dataset, and a least-privilege service account, so the whole platform can be torn down and rebuilt from code.
- Monthly batch ingestion. A Python extractor pulls each month from the USGS API (magnitude 1.0 and above) and writes Parquet to Cloud Storage, with a backfill path that replays from January 2015 to the present.
- Cost-aware warehouse design. An external table reads the raw Parquet, then a materialized table is defined with PARTITION BY DATE_TRUNC(event_date, MONTH) and CLUSTER BY mag_category, region, which limits bytes scanned for the dashboard's most common filters.
- Layered transformations. dbt stages the raw events, enriches them with derived fields such as magnitude and depth categories, and produces a fact table plus a monthly aggregate.
- Geospatial output. Coordinates and depth survive into the mart, so the same model supports mapping, regional ranking, and depth-versus-magnitude analysis.
- Dashboard. A Looker Studio report showing earthquake frequency per month (filterable by magnitude category) and the top countries by count for magnitude 5.0 and above, coloured by average magnitude.
Engineering decisions worth noting
- Why partition by month and cluster by magnitude and region. The dashboard always filters by time and usually by magnitude band or country. Partitioning on the date column prunes whole months, and clustering on the two most filtered columns keeps scans small, which is the main cost lever in BigQuery.
- Why Terraform instead of clicking through the console. A migration or rebuild should be a code change and a diff, not a set of undocumented console actions. This is also the habit I bring to client work.
- Why an external table before a materialized table. It keeps the raw Parquet auditable in Cloud Storage while the materialized, partitioned table does the heavy lifting for queries.
- Why monthly batches. The source updates continuously, but the analytical questions here are monthly trends. Batching monthly is the cheapest design that answers them.
Honest notes
This was my capstone project for the DataTalks.Club Data Engineering Zoomcamp 2026. The repository says so openly, and I built every layer of it end to end.
Orchestration here is Kestra, not Cloud Composer. I run Apache Airflow in production at work, and Composer is managed Airflow, but the Composer claim is transferability rather than hands-on use in this project.
The dbt layers are staging, intermediate, and marts. That is a layered warehouse, and I describe it that way rather than calling it a bronze, silver, and gold medallion build.
There are no automated dbt tests in this repository. My data-quality testing experience comes from production pipelines elsewhere, including reconciliation and freshness checks.