Everything worth knowing, nothing that isn't.
What each one actually protects against
A time-based code from an authenticator app is generated on the device from a shared secret and never travels over a network, so it is immune to SIM swap, SS7 interception and network-level snooping. An SMS code travels the operator network, which means it can be redirected by a SIM swap and, on poorly protected routes, intercepted at the signalling layer. Against ordinary password reuse and credential stuffing — by far the most common attack — both are effective.
What each one costs you in users
Authenticator apps have an enrolment cliff: the user must install an app, scan a code, and keep the device. A meaningful share will not complete that, and those who lose the device generate support load. SMS has no enrolment step at all — the user already has the number you have. In markets with lower smartphone penetration or where users change handsets often, SMS is not the weaker choice, it is the only one that works.
A sensible hierarchy
Offer passkeys or an authenticator app as the primary factor and make enrolling attractive. Keep SMS as the fallback so nobody is locked out. Reserve the highest-assurance flows — moving money, changing a payout account, disabling security controls — for the strong factor only, and add a line-status check so a recent SIM swap forces a step-up. That way the weak factor never guards the thing that would hurt most to lose.
If you can only ship one
Ship SMS OTP, and ship it well: direct operator routes so the code arrives in seconds rather than minutes, a short code lifetime, a low attempt limit, and a voice fallback for the small share of messages that never land. A well-delivered SMS code beats an authenticator app the user never enrolled in — and you can add the stronger factor later without taking the fallback away.