Postgres action — the differentiator

Write Stripe events to Postgres, your database

Pipe any Stripe event into your own Postgres database. Templated columns, upserts, idempotent retries. The action Stripe will never ship natively.

Free trial · From $19/mo · No credit card required

The problem

Every serious SaaS eventually needs Stripe data in its own database. Not Stripe's data warehouse, not a third-party CDP, your Postgres, the one with the user table that has a foreign key to billing. Today you write stripe events to postgres with a custom webhook handler, hosted somewhere, with retries, signature verification, and a schema you maintain by hand. Or you pay Fivetran $500+/mo to sync the whole Stripe object model on a delay. Both are heavy for what should be a workflow step.

The Postgres action is the one Stripe will not ship natively. Point it at your database with a connection string (sslmode required), map Stripe event fields to columns with JSONata, set an upsert key, and write. It runs as a step in Stripe Workflows. The data lands in your schema, in your timezone, with your column names, deduped on Stripe's invocation id. That's the whole differentiator.

How write stripe events to postgres works

  1. 1

    Add your connection string

    Paste a postgres:// URL into the action. Outbound requires sslmode=require, stores the string encrypted per account, and connects through a pool. Works with Neon, Supabase, RDS, Crunchy, Railway, self-hosted.
  2. 2

    Map event fields to columns

    Configure the target table and a column-to-JSONata mapping. Outbound infers column types from the database and validates the mapping on save. Type coercion handles numbers, timestamps, jsonb, and booleans without code.
  3. 3

    Set an upsert key (optional)

    Pick a column or set of columns that uniquely identify a row — usually a stripe id. Outbound builds an ON CONFLICT clause so re-running a workflow won't create duplicates. Skip the key and every execution appends.
  4. 4

    Publish and watch your tables fill

    The action writes one row per Stripe invocation. The execution log shows the row count, timing, and any constraint violations. Your queries return Stripe data the moment the event fires.
// outbound.postgres step in a Stripe Workflow
{
  trigger: 'invoice.paid',
  action: 'outbound.postgres',
  config: {
    connection_string_secret: 'PG_URL',
    table: 'stripe_invoices',
    upsert_key: ['stripe_invoice_id'],
    columns: {
      stripe_invoice_id: '{{invoice.id}}',
      customer_id:      '{{customer.id}}',
      amount_paid:      '{{invoice.amount_paid}}',
      currency:         '{{invoice.currency}}',
      paid_at:          '{{$fromMillis(invoice.status_transitions.paid_at * 1000)}}',
      raw:              '{{$}}'  // store full event as jsonb
    },
  },
}

Example workflow configuration

Screenshot of the Postgres action config inside the Stripe Workflow builder. Shows a connection string field with masked characters, a table picker dropdown listing tables from the connected database, a column-to-JSONata mapping grid with type indicators (text, int, timestamp, jsonb) next to each column, and an upsert key multi-select with two columns chosen.

Your schema. Your database. Stripe Workflows writes directly into it with type checking and upsert support.

Outbound vs custom webhook handler

Outboundcustom webhook handler
Hosted infrastructure to maintain
Signature verification + retriesbuilt-inyou build it
Idempotent on Stripe invocation idyou build it
Setup time≈5 minutes1-2 days
Pricing modelFrom $19/mo flatHosting + dev time
JSONata column templating
Lives inside the Stripe Dashboard

Frequently asked questions

Which Postgres flavors are supported?+
Anything that speaks the standard Postgres wire protocol over TLS. We test against vanilla Postgres 14, 15, 16, plus Neon, Supabase, AWS RDS, Crunchy Bridge, Railway, and Fly Postgres. CockroachDB and Aurora Postgres work but are best-effort.
How do you handle schema changes?+
Outbound reads the column list and types on every config save. If a column is dropped or its type changes incompatibly, the action fails fast on the next workflow publish rather than silently inserting garbage. You add a column, save, you're back online.
Can the connection go through a VPC or private network?+
v1 connects from a fixed set of Outbound egress IPs over public TLS, suitable for any provider that offers an SSL endpoint. Private-network access via PrivateLink or VPC peering is on the Pro roadmap; talk to support if you need it sooner.
What about transactional writes across multiple tables?+
The action writes one row to one table per execution. To write to multiple tables transactionally, point the action at a Postgres function (call_target: function) and let Postgres run the multi-statement transaction. This keeps the heavy schema knowledge in your database, not your workflow.
How do you keep credentials safe?+
Connection strings are encrypted at rest with a per-account key. They're never returned in the dashboard once saved, never logged, and only readable by the worker that executes your workflow. Rotate any time — the action picks up the new string on next save.