An SMS login flow looks simple: generate a code, send it, and verify the response. Roaming turns that operation into a chain of independent systems.

Your application may accept the request. Your messaging provider may accept the message. A carrier may route it toward the subscriber's home network. A visited network may register the handset. The phone may be connected but using the wrong SIM for messages. The destination service may also reject a number range or pause an account before any message is sent.

That is why “the code did not arrive” is not a diagnosis. It is only a symptom.

The goal is to make every stage observable, keep retries safe, and give users a useful next action when the route is uncertain.

Model delivery as a state machine