Payment workflows
When money is involved,
"we think it worked" isn't enough.
Payment webhooks are low-volume, high-stakes. A single missed or duplicated event can mean refunds, disputes, and broken customer trust. Here's how to prevent that.
Real payment webhook failure modes
These aren't hypotheticals. They're the calls that wake up engineers at 2 AM and the disputes that arrive 60 days later.
The duplicate charge
Stripe sends invoice.paid twice due to a network hiccup. Your system processes both. Customer is charged twice. Refund required, trust damaged.
Root cause: No idempotency key check at the gateway level.
The silent miss
A payment.failed webhook arrives during a deploy. Your endpoint returns 503. Stripe retries for 3 days, then gives up. You never know the payment failed.
Root cause: No storage before forwarding. No alerting on failures.
The dispute without evidence
Customer claims they never received confirmation. You know the webhook arrived, but you can't prove when, or what it contained. Dispute lost.
Root cause: No immutable audit trail of webhook payloads.
The reconciliation nightmare
End of month: your database says $50,000 in payments. Stripe says $52,000. Two hours of manual digging to find the three missed webhooks.
Root cause: No system of record for webhook events.
Why idempotency alone fails
The conventional wisdom
"Just make your webhook handlers idempotent. Check if you've seen the event ID before. Problem solved."
This works for simple cases. It fails for complex ones.
Where it breaks down
- Race conditions — Two duplicate webhooks arrive milliseconds apart. Both pass the "not seen before" check before either writes to the database.
- Partial processing — You record the event ID, then crash before completing the business logic. Event is marked "processed" but wasn't.
- No audit trail — You can prove you processed the event, but not what the event contained. In a dispute, that matters.
- Multi-service complexity — Your payment service is idempotent, but the inventory service that receives the same webhook isn't.
The better approach
Deduplication at the gateway level, before events reach your application. Database-level unique constraints that can't race. Immutable storage that proves what happened. Then idempotency in your handlers as a second layer of defense.
How Transyt prevents duplicates & missing events
Gateway-level deduplication
Every webhook is deduplicated before it reaches your app. Same provider event ID? Same account? We skip delivery. Your database stays clean.
How: PostgreSQL unique constraint on (account_id, provider_event_id)
Stored before forwarded
The webhook is written to our database before we return 200 OK to Stripe. If Stripe thinks we received it, we have it. Guaranteed.
How: Synchronous write to PostgreSQL, then async delivery
Immutable payment evidence
Original payload, headers, signature validation result, all timestamps. When disputes happen, you have proof that stands up to scrutiny.
How: No transforms, no mutations, no 'helpful' modifications
Reconciliation source of truth
Query all payment events by time range, amount, customer, or status. Export for reconciliation. The numbers will match.
How: Full-text search, filters, JSON export, API access
Transyt as a reconciliation source of truth
At the end of every month, your payment numbers need to match. Stripe says one thing. Your database says another. Where do you look?
Transyt stores every webhook before forwarding. Query by date range, event type, or amount. Find the gaps in seconds, not hours. Export the evidence.
Works with your payment stack
Stripe
HMAC-SHA256 signature validation. Deduplication by event ID. All webhook types supported.
PayPal
Certificate-based validation. IPN and webhook API support. Transaction ID deduplication.
Square
Signature verification. Event type filtering. Full payload storage.
Any payment provider
Generic HTTP webhook support. Custom signature validation. Same guarantees.
See how teams protect payment workflows with Transyt
Set up in 5 minutes. Every payment webhook stored, deduplicated, and proven.
Start free