null

Stripe Webhook Failing: Quick Fix for Server Admins

Server & Cloud Intermediate 👁 8 views 📅 Jun 29, 2026

Stripe webhooks failing? Usually a server timeout or SSL issue. Here's how to fix it fast without the fluff.

You're Not Alone—This Is a Server Issue, Not Stripe's Fault

I get it. You set up a Stripe webhook, tested it once, it worked. Then two days later, payments are going through but nothing's hitting your server. Emails not sending, subscriptions not updating. Frustrating. But 9 times out of 10, it's your server timing out or SSL acting up. Let's get it fixed in less than ten minutes.

The Fix: Increase Your Server Timeout

Stripe sends webhooks with a 5-second timeout. If your server doesn't respond in that window, Stripe marks it as a failure and retries up to 3 times over 24 hours. But if your server takes 6 seconds to process, it'll fail every time. Here's how to bump that timeout.

For Apache (mod_php or PHP-FPM)

Edit your php.ini file. Find max_execution_time and set it to 30. Also check max_input_time and set it to 30. Save and restart Apache.

max_execution_time = 30
max_input_time = 30

For Nginx with PHP-FPM

Edit your php.ini same as above. Then check /etc/php/8.x/fpm/pool.d/www.conf and add or uncomment:

request_terminate_timeout = 30s

Restart PHP-FPM: sudo systemctl restart php8.3-fpm

For Node.js (Express)

If you're using Express, add a timeout middleware. Here's a quick fix:

const timeout = require('connect-timeout');
app.use(timeout('30s'));
app.use((req, res, next) => {
  if (!req.timedout) next();
});

Also Check Your SSL Certificate

Last month I had a client whose Stripe webhook kept failing. Turned out their SSL cert expired that morning. Stripe's webhook infrastructure won't send to a server with a bad cert. Run this command to check yours:

echo | openssl s_client -servername yourdomain.com -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates

If it's expired, renew it through your hosting provider or Let's Encrypt.

Why This Happens

Stripe's webhook system is built for reliability. Their servers wait exactly 5 seconds for your server to respond with a 200 OK. If your code does a database query, sends an email, and calls an external API all in one webhook handler, that can easily chew up 4-5 seconds. Add network latency, and boom—timeout. The fix is simple: either process the webhook async (queue it) or increase the timeout to give yourself breathing room.

Less Common Variations

Sometimes it's not timeout. Here are other sneaky causes I've seen:

  • Signature verification failing: Your code checks the webhook signature but the key is wrong. Regenerate the signing secret in Stripe Dashboard and update your code.
  • IP whitelist blocking: If your server has a firewall, Stripe's IPs change. Add their full range: https://stripe.com/docs/ips. I've seen clients block them by accident.
  • HTTP redirect loop: If your webhook endpoint URL redirects (301/302), Stripe won't follow it. Must be a direct 200 response.
  • Response body too large: If your handler returns a massive JSON payload, Stripe might drop it. Keep your response small—just {"status": "ok"}.

How to Test Without Breaking Production

Use Stripe CLI to test locally. Install it, then run:

stripe listen --forward-to localhost:3000/webhook

Then trigger test events: stripe trigger payment_intent.succeeded. Watch your logs. If it fails locally, it'll fail on production.

Preventing This Long-Term

Don't process heavy tasks inside the webhook handler. Instead, push the event to a queue (Redis, RabbitMQ, or even a simple database table) and process it in a background job. That way your webhook endpoint just returns 200 instantly. Stripe loves that. Also set up monitoring: use UptimeRobot or Pingdom to check your endpoint every 5 minutes. And set up Stripe webhook logs alerts in the Dashboard—they'll email you when failures spike.

One more thing: if you're using a shared hosting plan, their default timeout is often 30 seconds, which is fine. But if you're on a VPS, the default PHP timeout can be 5 seconds. That's the same as Stripe's timeout—recipe for failure. Bump it to 30 and you're golden.

Had a client last month whose entire Stripe integration died because their webhook handler was sending a thank-you email via SMTP. That call took 8 seconds. After moving the email to a queue, webhooks worked instantly.

Was this solution helpful?