Trigger vs hook split is basically what I use too, so I'll just take the SMS question since nobody writes about that one. Stuff I've actually seen in prod with Send SMS:Routing for cost and deliverability is the obvious reason. Twilio's fine in US/EU but pricing and delivery rates get rough across a lot of APAC and LatAm, so people swap in Plivo, Telnyx, Bird, or a local aggregator (MSG91 or Gupshup if you're sending to India). Owning the send side is the whole point, you get to pick per region.Some teams don't even send SMS from it. One I worked with pushes the OTP over WhatsApp Business in markets where SMS just doesn't land, and only falls back to SMS if that fails. You get the phone number and the code in the payload so the channel is yours. The one I'd actually flag for you though is fraud. The real reason to own this path isn't the provider, it's SMS pumping. Bots hammer your OTP endpoint with numbers on premium-rate ranges and someone collects the revenue share. Supabase's built-in rate limits won't catch that. In the hook I run the number through libphonenumber, drop country codes I don't serve plus the known pumping ranges, and cap attempts per number and per IP before the provider ever gets called. Killed a slow monthly bleed doing exactly that on a previous app.On your latency point: if you're running the hook as an edge function, watch cold starts. They stack on top of the provider round trip and the whole thing sits in the OTP request path. A 3 second cold start on "text me a code" just feels broken to the user. For the SMS hook specifically I'd keep a warm endpoint instead. Your keep-hooks-fast rule matters double here since you're also blocked on an API you don't control. One thing I still haven't settled: how hard to fail when the provider errors. Right now I return the error and let them retry, but that leaks provider downtime straight onto the user. Anyone doing async send with optimistic success? Curious how you reconcile a code that never arrives.