
Every minute your checkout is broken costs real money. Unlike a slow page or a UI bug, a broken checkout flow stops revenue entirely. Yet checkout failures are often the last thing discovered through monitoring — because the web server is up, the homepage loads, and standard uptime checks show green.
Checkout flows involve your application server, your database, a payment gateway, and often email delivery for order confirmations. Any one of these failing breaks the entire flow.
A checkout flow returning a 200 on the cart page tells you:
/cart route renders without errorsIt doesn't tell you:
The most expensive checkout failures are ones where the page loads, the customer fills in their card details, and then gets an error at the final step — or worse, the payment goes through but the order isn't created.
# Flask
import stripe
@app.route('/health/checkout')
def checkout_health():
checks = {}
# 1. Test payment gateway connectivity
try:
stripe.api_key = os.environ['STRIPE_SECRET_KEY']
# Lightweight call — retrieve account info, don't create anything
account = stripe.Account.retrieve()
checks['payment_gateway'] = 'ok'
checks['payment_gateway_mode'] = account.get('env', 'live')
except stripe.error.AuthenticationError:
checks['payment_gateway'] = 'error: invalid API key'
except Exception as e:
checks['payment_gateway'] = f'error: {str(e)}'
# 2. Test database write path (order creation)
try:
db.execute('SELECT COUNT(*) FROM orders')
checks['orders_db'] = 'ok'
except Exception as e:
checks['orders_db'] = f'error: {str(e)}'
# 3. Test inventory/product lookup
try:
product = Product.query.first()
checks['product_lookup'] = 'ok' if product else 'warning: no products'
except Exception as e:
checks['product_lookup'] = f'error: {str(e)}'
# 4. Test email queue for order confirmations
queue_depth = get_queue_size('order-emails')
checks['email_queue_depth'] = queue_depth
checks['email_queue'] = 'ok' if queue_depth < 500 else 'degraded'
all_ok = all(v == 'ok' for v in [
checks.get('payment_gateway'),
checks.get('orders_db'),
checks.get('product_lookup'),
checks.get('email_queue'),
])
return jsonify({'status': 'ok' if all_ok else 'degraded', **checks}), \
200 if all_ok else 503
// Node.js / Stripe
app.get('/health/checkout', async (req, res) => {
const checks = {};
try {
// Test Stripe connectivity
const account = await stripe.accounts.retrieve();
checks.paymentGateway = 'ok';
// Test database
await db.query('SELECT COUNT(*) FROM orders');
checks.ordersDb = 'ok';
// Test cart/inventory service
const product = await Product.findOne();
checks.productLookup = product ? 'ok' : 'warning: empty catalogue';
const allOk = ['paymentGateway', 'ordersDb', 'productLookup']
.every(k => checks[k] === 'ok');
res.status(allOk ? 200 : 503).json({
status: allOk ? 'ok' : 'degraded', ...checks
});
} catch (err) {
res.status(503).json({ status: 'error', error: err.message, ...checks });
}
});
A checkout flow that takes 8 seconds to load loses customers before they even start. Response time monitoring catches performance degradation before it becomes complete failure.
Set an alert threshold: if /checkout takes more than 3 seconds, something in the stack is struggling — usually a slow database query or a slow external API call during page load.
If you use Stripe, monitor beyond just API connectivity:
Webhook endpoint availability — Stripe sends webhook events (payment confirmed, payment failed, refund processed) to your server. If your webhook endpoint is down, Stripe can't notify you and your order processing falls behind.
# Test your webhook endpoint is reachable
curl -I https://yourdomain.com/webhooks/stripe
See how to monitor Stripe webhooks and checkout flows for comprehensive Stripe monitoring including webhook health, test mode vs live mode checks, and delivery verification.
Stripe's own status — Stripe has its own status page at status.stripe.com. If Stripe is having issues, your checkout fails regardless of your application health. Monitor Stripe's API endpoint as a dependency alongside your own health check.
One of the most damaging checkout failures: your application is running in Stripe test mode in production. Orders appear to go through (test cards work), but no real payments are captured.
Add a check that verifies your Stripe key is a live key in production:
if os.environ.get('APP_ENV') == 'production':
assert os.environ['STRIPE_SECRET_KEY'].startswith('sk_live_'), \
'Stripe key is test mode in production!'
Surface this in your health check response so it's visible.
For products that involve fulfilment (physical goods, access provisioning, licence keys), the post-payment processing is as critical as the checkout itself. A successful payment followed by failed fulfilment is worse than a payment failure — the customer was charged but didn't receive what they paid for.
If fulfilment is queue-based, monitor queue depth and worker health. See how to monitor queue workers on Laravel, Node.js, and Python apps for the queue monitoring patterns.
Domain Monitor monitors your /health/checkout endpoint alongside your main site uptime. When your payment gateway becomes unreachable, your orders database has a problem, or your checkout page starts timing out, you're alerted within a minute — not when your sales dashboard shows a gap. Create a free account.
Wildcard, SAN (multi-domain), and single-domain SSL certificates cover different use cases. Here's a clear comparison to help you pick the right type — and avoid paying for coverage you don't need.
Read moreDNS resolves correctly from your office but fails for users in other countries or on different ISPs. Here's why geographic DNS inconsistency happens and how to diagnose which layer is causing it.
Read moreRegistrar lock and transfer lock are often confused — and disabling the wrong one leaves your domain vulnerable. Here's a clear breakdown of what each does and when to use them.
Read moreLooking to monitor your website and domains? Join our platform and start today.