getdriftless.dev

Your Postgres never drifts from Stripe.

Driftless is a single binary that receives Stripe webhooks, finds the events Stripe never delivered, backfills history, and materializes everything into a stripe schema in your own Postgres. Then it proves the result: driftless verify reconciles your database against Stripe and exits nonzero on drift.

Apache-2.0 · self-hosted · read-only against Stripe · no third party touches your payment data

the problem

Webhook delivery is at-least-once, unordered, and silently droppable.

Stripe's own engineering blog says so, and teaches you to build queues and reconciliation jobs around it (their words). Teams discover the damage late:

And the evidence expires: Stripe's event log only goes back roughly 30 days. After that, a gap is not recoverable from events at all.

quickstart

Ten minutes from zero to a proven-correct mirror.

You need Postgres 17+, a Stripe API key (a restricted read-only rk_... key is recommended), and a webhook signing secret.

# 1. Install: one static binary, no runtime
curl -fsSL https://raw.githubusercontent.com/quyumkehinde/driftless/main/scripts/install.sh | sh

# 2. Point it at your Postgres and your Stripe account
export DRIFTLESS_DATABASE_URL='postgres://...'
export DRIFTLESS_STRIPE_API_KEY='rk_test_...'
export DRIFTLESS_STRIPE_WEBHOOK_SECRET='whsec_...'

# 3. First-run setup: environment checks, migrations, offer of a backfill
driftless init

# 4. Run it
driftless serve

# ...and locally, forward Stripe's webhooks to it
stripe listen --forward-to localhost:8724/webhooks/stripe

# 5. Prove it
driftless verify --full

Exit 0 means your database provably matches Stripe. Exit 3 means drift, with a per-object report, and verify --repair fixes it. Put that exit code in CI and billing drift becomes a failing check.

In production, add https://<your-host>/webhooks/stripe as an endpoint under Developers → Webhooks in the Stripe dashboard, and subscribe to the event types you mirror or to all events. Types Driftless does not model are still stored, never dropped.

Prefer containers? A Docker Compose quickstart, a distroless image at ghcr.io/quyumkehinde/driftless, and Kubernetes manifests ship in deploy/.

using it

Reads become SQL. Reactions become LISTEN/NOTIFY.

Anywhere you call the Stripe API or maintain hand-rolled billing state, query the mirror instead, and join it against your own tables:

-- can this user access the product?
SELECT s.status IN ('active', 'trialing')
FROM stripe.subscriptions s
JOIN app.users u ON u.stripe_customer_id = s.customer
WHERE u.id = $1 AND NOT s.is_deleted;

Anywhere you would write a webhook handler, listen instead. Every applied change fires pg_notify on driftless_changes in the same transaction as the write; your worker re-reads the row and acts. By then the state is committed, deduplicated, and ordered: no payload parsing, no signature checks, no duplicate or out-of-order handling in your code.

LISTEN driftless_changes;
-- {"type": "subscription", "id": "sub_123"}: read the row, act

What you delete from your codebase: the webhook endpoint, the dedupe table, the resync cron. The raw event log stays queryable past Stripe's 30-day window as your audit trail.

what it does

Everything between Stripe and your database.

receive
Signature-verified webhooks; Stripe is acknowledged only after the event is durably committed.
dedupe
Every event recorded exactly once; state converges regardless of duplicates, ordering, or same-second ties.
gap sweep
A sweeper finds events Stripe generated but never delivered, before the 30-day cliff erases them.
backfill
Full or incremental history, resumable across kill -9, including the canceled subscriptions the default listing hides.
materialize
Typed, indexed stripe.* tables with the raw JSON preserved alongside.
prove
A reconciliation report with an exit-code contract, and a repair mode that trues up whatever it finds.

At-least-once delivery, exactly-once processing, provable convergence. Nobody can give you exactly-once delivery, so that is what Driftless promises instead.

alternatives

How it compares.

Driftless stripe/sync-engine Hookdeck / Svix Airbyte / Fivetran
Dedupe guaranteed yes partial best-effort n/a
Out-of-order and same-second safe yes known open issue no n/a
Detects never-delivered events yes no no no
Backfill incl. canceled subscriptions yes known open issue no polling sync
Reconciliation proof verify, exit-code contract no no no
Where your data lives your Postgres your Postgres their cloud, then yours your warehouse, hours later

Already running stripe/sync-engine? driftless import --from-sync-engine migrates a database in place: one schema rename, one import, one verify --repair.

managed driftless

Rather not be on call for it?

Everything that makes the mirror trustworthy lives in the open source binary and always will; a paid tier, if one ever exists, only adds hosting and dashboards on top. If that is the part you would pay for (fleet dashboard, drift history, alert routing), leave an email. No newsletter; one message if it ships.