Take Postgres beyond pg_cron and nightly scripts.

Postgres stores and queries the data. Kestra decides when each job runs, what feeds it, and what runs next: bulk-load files the moment they land, run transactional multi-statement loads, react to row changes with CDC, and trace every statement in one execution history.

Blueprints for Postgres orchestration.

pg_cron schedules SQL inside one database on a clock. Kestra runs everything around Postgres: it downloads a file and bulk-loads it with COPY the moment it arrives, chains Postgres with dbt transforms and S3 in one flow, runs multi-statement loads as a single transaction so a partial batch never lands, and reacts to row changes with Debezium CDC. Every run gets retries, backfills, and a logged history that pg_cron cannot give you.

Download a file and bulk-load it with COPYOpen blueprint
Run a flow whenever Postgres rows changeOpen blueprint
Run dbt build on Postgres from GitOpen blueprint
Browse all 60 Postgres blueprints

Above the database scheduler.

Postgres runs the storage, the queries, and the COPY. Kestra runs the steps around the query: what triggers it, what feeds it, what runs next, and where the cross-tool audit trail lives.

Event-driven jobs, not database cron

pg_cron fires SQL inside one database on a fixed clock. If the upstream extract slips, it runs on stale data. Kestra triggers io.kestra.plugin.jdbc.postgresql.Query the moment the upstream step confirms, whether that is a file landing in S3, a webhook, or an Airbyte sync. The Trigger task also polls Postgres and starts a flow when a query returns rows.

Bulk loading orchestrated end to end

Loading a file means download it, create the table, COPY it in, then validate the count. Kestra runs core.http.Download, then io.kestra.plugin.jdbc.postgresql.CopyIn over the COPY protocol (the fastest path in Postgres), then a row check as ordered steps with per-step retries. A failed COPY retries without re-downloading the file.

Transactional multi-statement loads

An incremental load is rarely one statement: stage the rows, MERGE into the target, dedup, update a watermark. io.kestra.plugin.jdbc.postgresql.Queries runs them as one transaction, so a failure rolls back and a half-applied batch never lands. The next run resumes cleanly from the last committed watermark.

Full ELT in one flow

Postgres has no view of the connector that fed it or the dbt models that read it. Kestra runs ingestion, the Postgres load, the transform, and the reverse-ETL push as steps in one flow. Run IDs flow forward and the whole chain shares one execution ID, so you debug load, transform, and sync from one screen, not three.

Real-time CDC with Debezium

Time-based scheduling cannot react to a single changed row. io.kestra.plugin.debezium.postgres.RealtimeTrigger reads the Postgres write-ahead log and starts one execution per change, so inserts and updates fan out to downstream systems like Kafka the instant they commit, with no polling lag and no missed rows.

Self-service queries for analysts

Analysts should not need database credentials to run a parameterized export. Kestra Apps wraps a Query flow in a typed form: pick the date range, run the query, get the result file. Every run lands in execution history with the requesting user, so self-service does not mean unaudited.

How teams use Postgres and Kestra

Patterns data engineering teams run in production today. Each one shows the flow end to end, with the real plugin classes in play.

Bulk load

Extract and bulk-load files into Postgres

A CSV lands or an API exposes a dataset. Kestra downloads it, runs a Query to create the table if needed, then bulk-loads it with CopyIn over the COPY protocol. A row-count check gates anything downstream, and a failed load retries without re-downloading the file.

COPY, not row-by-row inserts

CopyIn streams the file in one operation, the fastest load path in Postgres.

Validate before downstream

An If branches on the loaded row count before anything reads the table.

Retry the load in isolation

A COPY failure retries on its own without re-running the download.

Download icon
download
fetch file
Query icon
create table
DDL
CopyIn icon
copy in
bulk load
If icon
row check
validate
Parallel ETL

Fan one extract out to Postgres and S3 at once

One source, two sinks. Kestra downloads the data, transforms it in Python, then writes it in parallel to Postgres with CopyIn and to S3 as a backup. Each write is isolated, so a slow S3 upload never blocks the database load, and an email confirms with the row count.

Transform once, load twice

A single Python step shapes the rows for both Postgres and the S3 archive.

Per-sink failure isolation

Each sink writes independently, so one slow target never blocks the other.

Seconds, not minutes

Extract, transform, and a dual load finish in one short execution.

Download icon
download
fetch source
Script icon
transform
shape rows
CopyIn icon
copy in
load Postgres
Upload icon
s3 upload
archive
MailSend icon
email
row count
ELT

Transform in place with dbt from Git

Models live in version control, not in the database. Kestra clones the dbt project, runs dbt build against Postgres in a container, then posts to Microsoft Teams. A failing test stops the chain before downstream consumers read half-built tables.

Models stay version-controlled

git.Clone pulls the exact committed dbt project before every build.

Tests gate the build

A failing dbt test halts the flow before consumers read the tables.

Swap the target database

Point the same flow at Snowflake or Redshift by changing the dbt profile.

Schedule icon
schedule
nightly
Clone icon
git clone
pull dbt project
DbtCLI icon
dbt build
transform
TeamsIncomingWebhook icon
teams
on complete
CDC

React to Postgres row changes in real time

Some pipelines react to data, not clocks. The Debezium Trigger reads the Postgres write-ahead log and starts a flow the moment rows change, posts the change count to Slack, then processes the captured payload in Python. No polling lag, no missed commits.

Capture from the WAL

Debezium streams inserts, updates, and deletes straight from the write-ahead log.

One execution per change batch

Each committed change set starts its own run with the payload attached.

Process in any language

The captured JSON flows into a Python, shell, or SQL step for downstream work.

Trigger icon
debezium trigger
WAL change
SlackIncomingWebhook icon
slack
change count
IonToJson icon
to json
serialize
Script icon
process
downstream work
Reverse-ETL

Sync changed Postgres rows to a SaaS app

Operational data lives in Postgres, but the sales team works in the CRM. The Postgres Trigger polls for changed rows, fans them out with ForEach, and creates or updates each record in HubSpot, so the CRM stays current without a nightly batch and a Discord ping confirms the run.

Poll only the changed rows

The Trigger query returns new or updated records, not the whole table.

Fan out per record

ForEach creates or updates each row in the destination independently.

Any SaaS destination

Swap the HubSpot task for Salesforce, Slack, or any API target.

Trigger icon
postgres trigger
changed rows
ForEach icon
for each
per record
Create icon
hubspot
create or update
DiscordIncomingWebhook icon
discord
on complete
Our goal is for Kestra to become the go-to solution across the organization whenever data wrangling and complex pipeline orchestration are needed.
Rémi Sultan, AI/ML Lead at Gravitee
50%reduction of pipeline maintenance time
2engineers to build the product

Kestra vs the orchestration alternatives Postgres teams evaluate

Capability
pg_cron
Airflow
Dagster
Trigger jobs on upstream completion or events
Native event + flow triggers
Cron inside the database onlySensor-based pollingSensors, Python required
Move data across systems, not just run SQL
HTTP, S3, dbt, APIs as tasks
SQL in one database onlyOperators, Python requiredOps and assets, Python required
Bulk load files with COPY
CopyIn and CopyOut tasks
Hand-written SQL onlyPythonOperator glueCustom op
Transactional multi-statement load
Queries in one transaction
Hand-written PL/pgSQLOperator chainCustom op
React to row changes with CDC
Debezium trigger, one run per change
No, time-based onlyCustom sensorCustom sensor
Retries, backfills, replay from failure
Per-task, built in
NoneYes, Python configYes, Python config
Declarative YAML, IaC-friendly
YAML + Terraform provider
SQL DDLPython DAGsPython assets

Postgres & Kestra: common questions

Find answers to your questions right here, and don't hesitate to Contact Us if you couldn't find what you're looking for.

See How

Ready to orchestrate your Postgres pipelines?

Bulk-load files with COPY, run transactional loads, react to row changes with CDC, and chain Postgres with dbt and object storage in one flow. Open source, self-hosted, event-driven.