DEV Community

Mahad Tahir
Mahad Tahir

Posted on

I Lost a Customer Because of a 500 Error I Never Saw — So I Built Webhook Proxy

Stop Building Redis + BullMQ Just to Retry a Failed Webhook

Let me tell you about the worst kind of bug: the one that doesn't throw an error, doesn't page you, and doesn't show up in your logs — because there are no logs.

The 3am problem nobody talks about

A customer pays through Stripe. Stripe fires a webhook to activate their account. Your server — cold start, mid-deploy, flaky DB connection, whatever — returns a 500 or just times out.

Stripe did try to notify you. Your endpoint did fail. And unless you built retry logic in advance, that event is gone from your visibility right now. You find out three days later when a customer emails asking why they paid but never got access.

That's not a bug in your business logic. That's a bug in your plumbing — and plumbing bugs are the worst because they're invisible until someone's money is involved.

If you're gluing together Stripe → Zapier → Make → your API, this isn't hypothetical. It's a matter of time.

Why "just add retry logic" is bad advice for indie projects

The textbook answer is: spin up Redis, add BullMQ, write backoff logic, build a dead-letter queue. Great advice if you're a team of 12 processing a million events a day. Total overkill if you're a solo founder trying to see "hey, this failed, let me hit retry."

Most indie webhook failures aren't exotic distributed-systems problems — they're mundane. A deploy took 40 seconds too long. A downstream API hiccuped for 10 seconds. You don't need a queueing system for that. You need a safety net.

The fix: put a proxy in front of your endpoint

This is why I built Webhook Proxy — a layer that sits between Stripe/Zapier/Make and your endpoint so events never just vanish.

  1. Swap the URL — point your webhook destination at Webhook Proxy instead of your real endpoint. No SDK, no code changes.
  2. Auto Buffer — it forwards the event to your endpoint, and catches it if your endpoint 500s or times out.
  3. Real-time JSON Log — every payload stored raw, so you can actually see what was sent.
  4. 1-Click Retry — see a failure, click retry, done.

You're not replacing your backend logic — you're adding a layer that's got your back when it falls over.

Technical Highlights

  • 🪵 Raw JSON Logging — every payload captured exactly as received
  • ⚠️ Error & Timeout Catching — 500s and timeouts caught, never silently dropped
  • 🔁 1-Click Manual Retries — replay any failed event straight from the dashboard
  • 🚫 Zero SDK, Zero Install — works with any provider that lets you set a webhook URL
  • 🆓 Free Tier — 5,000 webhooks/month, no card required

Try it

If a webhook has ever failed silently on you and you only found out because a customer complained — you know exactly why this exists.

Test the free tier → webhook-proxy-zeta.vercel.app


Genuine question: how are you currently handling failed webhooks — silently retrying and hoping, manually resending from the provider's dashboard, or something custom? Curious how far people take this before it becomes too much infra for the problem.

Top comments (0)