Stack guide
Stripe webhooks on serverless: Vercel and Lambda patterns
Serverless platforms deliver webhooks with three guarantees that matter: at-least-once delivery, execution time limits, and cold starts. Stripe’s sender treats timeout as failure and retries — so a slow-but-successful handler manufactures phantom failures that become duplicate processing. Architecture answers all three: split runtimes by responsibility, claim before work, and design handlers that tolerate their own repetition.
The Edge/Node split, drawn from production
Signature verification needs speed and public inputs — Edge excels. Detection math needing secret-derived crypto stays Node. Receiver verifies, claims durably, enqueues; workers process with full runtime freedom. FeeGuard’s own architecture follows exactly this shape, for exactly these reasons.
Timeout → retry → duplicates
Handler exceeding limits returns failure to Stripe despite completing work; redelivery repeats it. Claim-before-work breaks the chain: durable store marks event claimed atomically; repeat deliveries observe claims and exit early. Database unique constraints serve adequately at modest scale.
Cold starts versus race windows
Five-second race windows between paired events collide awkwardly with cold starts — delays implemented inside queues rather than handler sleeps keep timing deterministic under scale. Durable queues (managed or self-hosted) provide the delay-and-serialize primitives handlers cannot.
Design statement
Handlers should be idempotent, quick, and delegating: verify, claim, enqueue, acknowledge. Everything interesting happens downstream where retries cost nothing and state survives function lifetimes.
Common questions
Can we process synchronously in-handler?
Small volumes, maybe. Races plus timeouts make it expensive lessons at scale — the queue indirection pays for itself quickly.
Does this require a FeeGuard integration?
No — the page stands alone as stack guidance. FeeGuard observes your event stream externally rather than embedding in it.