List icon
If icon
Script icon
Docker icon
Query icon
AwsCLI icon
Schedule icon

Ingest data to AWS S3 with Python, Apache Iceberg, AWS Glue and Athena

Detect new S3 files hourly, clean CSVs with Python and awswrangler, then upsert into an Apache Iceberg table on AWS Glue and Athena with Kestra.

Categories
Data

Build an end-to-end ingestion pipeline that lands raw CSV files into an Apache Iceberg data lake on AWS. This blueprint detects new files in an Amazon S3 bucket, cleans and deduplicates them with Python and awswrangler, writes the result to an Iceberg table backed by AWS Glue, merges new records into a curated table with Amazon Athena, compacts small files, and archives processed inputs. It turns messy, periodically arriving CSV drops into a queryable, ACID-compliant lakehouse table without a separate ETL service.

How it works

  1. The list_objects task (io.kestra.plugin.aws.s3.List) lists objects under the prefix in the configured S3 bucket.
  2. The check task (io.kestra.plugin.core.flow.If) evaluates outputs.list_objects.objects and only runs the downstream steps when new files exist.
  3. The ingest_to_datalake task (io.kestra.plugin.scripts.python.Script) runs in a Docker taskRunner, installs awswrangler and kestra, reads the CSVs into a dataframe, filters and deduplicates rows, emits a nr_rows counter, and writes to an Iceberg table via wr.athena.to_iceberg.
  4. The merge_query task (io.kestra.plugin.aws.athena.Query) runs a MERGE INTO to upsert raw records into the curated fruits table.
  5. The optimize task runs OPTIMIZE ... REWRITE DATA USING BIN_PACK to compact small files.
  6. The move_to_archive task (io.kestra.plugin.aws.cli.AwsCLI) moves processed files to an archive/ prefix.
  7. The hourly_schedule trigger (io.kestra.plugin.core.trigger.Schedule, @hourly, disabled by default) drives the cadence.

What you get

  • An ACID Iceberg table on S3, managed by AWS Glue and queried through Athena
  • Automatic skip when no new files are present
  • Deduplicated, filtered data via Python and awswrangler
  • Upsert (MERGE) semantics into a curated table
  • File compaction and automatic archival of processed inputs

Who it's for

  • Data engineers building lakehouse ingestion on AWS
  • Analytics teams curating CSV drops into Athena-queryable tables
  • Platform teams standardizing S3-to-Iceberg pipelines

Why orchestrate this with Kestra

Athena, Glue, and S3 have no shared scheduler that can chain a conditional file check, a Python transform, SQL merges, and a CLI archive step into one observable run. Kestra adds event and schedule triggers, retries, full execution lineage, and declarative YAML so the entire flow is versioned and reproducible. The If task gives you native conditional branching that AWS analytics services cannot express on their own.

Prerequisites

  • An S3 bucket, AWS Glue database, and Athena workgroup
  • Docker available for the Python task runner

Secrets

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_DEFAULT_REGION

Quick start

  1. Add the three AWS secrets above to your Kestra instance.
  2. Set the bucket, prefix, and database variables to match your environment.
  3. Drop a CSV file under the configured prefix in S3.
  4. Execute the flow, then enable the hourly_schedule trigger for continuous ingestion.

How to extend

  • Swap the Python cleaning logic for your own schema and validation rules
  • Replace the Schedule trigger with an S3 event trigger for near-real-time ingestion
  • Add partition columns or table properties to the Iceberg write
  • Send a Slack or email notification after a successful merge

Links

Orchestrate with Kestra
Orchestrate AWS with Kestra
Share this Blueprint
See How

New to Kestra?

Use blueprints to kickstart your first workflows.