Hardening Third-Party API Timeouts (Twilio & Stripe)
Hardening Third-Party API Timeouts — Twilio & Stripe
Release: v0.1.110
Control: ERR-10
Category: Error Resilience
Background
The sanctions screening platform makes outbound calls to several external services:
| Service | Purpose |
|---|---|
| Twilio SMS API | Alert notifications to compliance users |
| Stripe SDK | Payment and billing operations |
| OFSI / UN / EU / OFAC | Nightly sanctions list sync |
Prior to v0.1.110, the sanctions-list fetch calls already used AbortSignal.timeout() to cap connection time. However, the Twilio fetch call in src/lib/sms.ts and the Stripe SDK client in lib/stripe.ts had no timeout configuration. A hung or unresponsive connection to either service would block the request thread indefinitely until the remote closed the connection or the process was killed.
What Was Fixed
Twilio — src/lib/sms.ts
The raw fetch call to the Twilio SMS API now includes an AbortSignal:
// Before
fetch(twilioUrl, {
method: 'POST',
headers: { ... },
body: params,
});
// After
fetch(twilioUrl, {
method: 'POST',
headers: { ... },
body: params,
signal: AbortSignal.timeout(10000), // 10-second hard limit
});
If Twilio does not respond within 10 seconds, the fetch is aborted and an AbortError is thrown, allowing the caller to handle the failure gracefully rather than waiting indefinitely.
Stripe — lib/stripe.ts
The Stripe SDK client is now instantiated with an explicit timeout option:
// Before
new Stripe(process.env.STRIPE_SECRET_KEY);
// After
new Stripe(process.env.STRIPE_SECRET_KEY, {
timeout: 10000, // 10-second hard limit
});
The Stripe Node SDK respects the timeout option (in milliseconds) on all underlying HTTP requests it makes.
Why This Matters
- Predictable failure modes — A 10-second ceiling turns an indefinite hang into a fast, catchable error.
- Consistency — All third-party HTTP calls in the platform now share the same 10-second timeout policy.
- Operational safety — In high-load or degraded-network conditions, a stalled Twilio or Stripe call can no longer cascade into request queue exhaustion.
No Action Required
This is a behind-the-scenes resilience improvement. There are no changes to:
- Environment variables
- API request/response contracts
- User-facing screens or notification behaviour
The timeout values are hard-coded to 10,000 ms (10 seconds) for both services, matching the existing timeout applied to sanctions-list fetch calls.