New to Kestra?
Use blueprints to kickstart your first workflows.
Automatically sync new and updated customer rows from Postgres into Salesforce Contacts with Kestra. Event-driven CRM data sync with retries and full lineage.
Keep Salesforce in sync with your operational Postgres database without manual exports or brittle scripts. This blueprint watches a customers table for new and updated rows, then creates matching Contact records in Salesforce so your sales and revenue teams always work from fresh data. It closes the gap between your application database (the source of truth for customer signups and profile changes) and your CRM (where those people become leads, contacts, and pipeline), turning a recurring data-entry chore into a reliable, hands-off pipeline.
io.kestra.plugin.jdbc.postgresql.Trigger polls Postgres every PT5M using fetchType: FETCH. Its SQL selects first_name, last_name, and email (aliased to FirstName, LastName, Email) from customers where updated_at is within the last day and the row has not yet been processed (processed_at IS NULL OR processed_at < updated_at).{{ trigger.rows }}.io.kestra.plugin.core.flow.ForEach task iterates over each row in {{ trigger.rows }}.io.kestra.plugin.ee.salesforce.Create creates a Contact in Salesforce, mapping the fetched values via {{ json(taskrun.value).FirstName }}, LastName, and Email onto the Contact object.Postgres connection settings are centralized in pluginDefaults for io.kestra.plugin.jdbc.postgresql, so every JDBC task inherits the same url, username, and password.
ForEach loop.A database cursor or a Salesforce import wizard cannot react to changes on its own, cannot retry a failed API call without losing context, and gives you no record of what was synced when. Kestra runs this as an event-driven pipeline: the Postgres trigger fires the moment qualifying rows appear, every Salesforce call is observable with retries and alerting, and each execution is captured as lineage you can inspect and replay. The whole pipeline is declarative YAML kept in version control, so changes are reviewable and reproducible across environments, something neither Postgres nor Salesforce schedulers can offer on their own.
customers table containing first_name, last_name, email, updated_at, and processed_at columns.SALESFORCE_USERNAMESALESFORCE_PASSWORDSALESFORCE_AUTH_ENDPOINTThe Postgres url, username, and password are supplied through flow variables (vars.postgres_url, vars.postgres_username, vars.postgres_password) referenced in pluginDefaults.
postgres_url, postgres_username, and postgres_password variables for your database.customers table exposes the expected columns.records block and columns to the trigger SQL.processed_at after a successful Salesforce call to make the pipeline idempotent.interval or replace the polling trigger with a webhook for true event-driven syncs.