New to Kestra?
Use blueprints to kickstart your first workflows.
Build a CSV-to-Postgres ETL pipeline with Kestra. Download a remote file, run DDL to create the table, and bulk load rows with CopyIn, all in declarative YAML.
This blueprint builds a complete CSV-to-Postgres ingestion pipeline that downloads a remote CSV file, creates the destination table with a DDL statement, and bulk loads the rows into PostgreSQL. It solves a common ETL problem: getting flat-file data into a relational database reliably, with the schema defined up front and the load step decoupled from extraction so each step can be retried and observed independently.
extract task (io.kestra.plugin.core.http.Download) fetches a remote orders.csv file over HTTP and stores it in Kestra internal storage, exposing its location as outputs.extract.uri.query task (io.kestra.plugin.jdbc.postgresql.Query) runs a create table if not exists DDL statement to define the orders schema (order id, customer name and email, product id, price, quantity, total) before any data lands.load_to_postgres task (io.kestra.plugin.jdbc.postgresql.CopyIn) streams the downloaded file into the target table using Postgres COPY, with format: CSV and header: true so the column header row is skipped.The connection target and table name are driven by the db and table variables, keeping the flow easy to repoint at another database or schema.
{{ secret('DB_PASSWORD') }}.psql scripts into a managed, observable pipeline.Postgres has no native scheduler or pipeline engine of its own. Kestra adds event and schedule triggers, automatic retries on transient failures, full execution lineage across the download, DDL, and load steps, and a declarative YAML definition you can version control. The bulk COPY path stays fast while gaining the orchestration, monitoring, and dependency management that plain SQL scripts lack.
DB_PASSWORD: the password for the Postgres user used by the query and load_to_postgres tasks.DB_PASSWORD secret to your Kestra instance.db variable to point at your Postgres JDBC URL and set table to your target table.docker run -d --name mypostgres -v mypostgresdb:/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=topSecret42 -e POSTGRES_DB=postgres postgres:latest
extract URI for your own CSV source or an upstream API.Schedule or Flow trigger to run the load on a cadence or on upstream completion.