DEV Community

EphraimPierce7934
EphraimPierce7934

Posted on

Capacity Planning SMS OTP and Email 2FA (For US/EU Student Report Releases)

Short answer: choose SMS OTP or an email verification code for login 2FA by modeling the report-release peak, the independently useful recovery path, and the evidence your US/EU operation can retain. SMS creates channel separation when the report goes to email; email is easier when the mailbox is already the approved identity boundary. Neither is automatically cheapest, easiest, or more deliverable once retries, support, abuse controls, and on-call work enter the calculation.

For an education platform, average traffic is a distraction. Generated reports tend to become available in batches, and every learner or guardian who arrives at once can create a code request, a repeated send, and a support contact while the attachment pipeline is busy doing separate work. I treat that release window as the bounded incident before launch: if one transport slows, what remains safe, what remains explainable, and which queue consumes the login SLO first? This is a planning exercise, not a story about an incident that happened.

The invariant is blunt: authentication capacity must be reserved independently of attachment generation and delivery.

Retry pressure spends the failure budget first

Start from concurrent report viewers during the busiest release window, then apply an explicit repeat-send allowance and headroom. Don't derive login capacity from monthly active users, and don't let an attachment worker hold an authentication worker, connection pool, or retry budget. The two workflows meet only after successful verification authorizes access to a particular report. That separation makes a useful compliance artifact: a reviewer can see that pressure in report generation cannot silently weaken the login control or extend a code's policy.

The planning inputs should be named rather than buried in a spreadsheet formula: expected peak starts per second, permitted sends per challenge, planned headroom, channel share, and the transport's sustainable acceptance rate for the relevant region. None of those inputs is universal. A US campus and an EU tutoring service may need different repeat-send assumptions; observed enrollment behavior and a load test against the team's own adapters would resolve that uncertainty.

Use a small model and keep its output in the release record. This Go example is deliberately a calculator, not a sender, so it cannot accidentally become an undocumented retry loop:

package capacity

import (
    "errors"
    "math"
)

type Plan struct {
    PeakStartsPerSecond float64
    MaxSendsPerLogin    int
    HeadroomRatio       float64
    SMSShare            float64
}

type RequiredRate struct {
    SMSPerSecond   int
    EmailPerSecond int
}

func Calculate(p Plan) (RequiredRate, error) {
    if p.PeakStartsPerSecond <= 0 || p.MaxSendsPerLogin < 1 {
        return RequiredRate{}, errors.New("peak and send allowance must be positive")
    }
    if p.HeadroomRatio < 1 || p.SMSShare < 0 || p.SMSShare > 1 {
        return RequiredRate{}, errors.New("invalid headroom or channel share")
    }

    total := p.PeakStartsPerSecond * float64(p.MaxSendsPerLogin) * p.HeadroomRatio
    return RequiredRate{
        SMSPerSecond:   int(math.Ceil(total * p.SMSShare)),
        EmailPerSecond: int(math.Ceil(total * (1 - p.SMSShare))),
    }, nil
}
Enter fullscreen mode Exit fullscreen mode

The model forces a useful argument. If the proposed email path has ample throughput but the mailbox is also where the sensitive attachment arrives, capacity alone cannot make it an independent factor. If SMS separates the destinations but the organization cannot support phone-number changes or regional delivery behavior, architectural separation has purchased a new operational gap. Capacity is necessary evidence, not the whole decision.

Load-test the challenge service and each transport adapter independently, then run the report publication workload beside them. Record queue age and completion latency by channel and region, while keeping raw destinations and submitted codes out of general telemetry. A single global success ratio hides the exact population that will call support.

No averages.

How should teams capacity-plan SMS OTP and email verification for US/EU login 2FA?

That question has three different answers: transport acceptance, user completion, and recovery. Pick an SLO for the user-visible login journey, assign a latency budget to challenge creation and transport, and leave enough time for a person to retrieve and enter the code. A transport can consume its budget without changing the authorization result; the challenge service should remain the authority for expiry, attempt limits, and successful use.

For SMS, template bytes affect the capacity plan. The referenced segmentation guidance states that a GSM-7 message fits up to 160 characters in one segment, while UCS-2 fits 70. Concatenated messages carry 153 GSM-7 or 67 UCS-2 characters per segment. A translated template or a punctuation change can alter the encoding and therefore the number of segments sent for one login. Review the rendered template used in every supported locale, store its approved version with the deployment evidence, and calculate transport demand from segments rather than assuming that one code request always means one segment.

Tiny character. Bigger queue.

Email shifts the operational checks. Google's sender guidelines require SPF or DKIM for all senders to Gmail accounts and specify additional requirements for bulk senders. Authentication setup, bounce handling, complaint monitoring, and sender-domain ownership therefore belong in readiness review, rather than being left to the team after a report release. The email containing a verification code should also be operationally separate from the job that generates and attaches the report, even if both ultimately use email, because the login SLO should not inherit attachment processing time.

Deliverability should be measured at the user journey, not declared as a property of a protocol. Track challenge starts, send attempts, user completions, expirations, and recovery starts by region and channel. Avoid treating a repeated send as free capacity or as proof that the first message failed; it is another bounded attempt with its own cost and abuse surface. Alert on sustained SLO burn and queue age, then use individual transport events for diagnosis rather than paging on every isolated non-completion.

Recovery determines the security and compliance boundary

SMS is useful in this scenario when an independently enrolled phone separates the login code from the inbox receiving the generated report. That is a concrete boundary, but it isn't magic. Shared phones, changed numbers, and recovery policy can reconnect paths that looked independent on an architecture diagram. Requiring SMS also means collecting and governing a phone number that email-only delivery might not otherwise need.

Email verification avoids introducing a phone-number lifecycle when the institution already treats the mailbox as the approved identity and recovery boundary. The catch is obvious: if the same mailbox receives both the code and the report attachment, access to that mailbox controls both steps. Calling the flow “2FA” doesn't create independence. Where the threat model requires a separately controlled factor, use one that is independently enrolled; SMS may fit, but email to the report mailbox does not satisfy that particular boundary.

Decision evidence SMS OTP Email verification code
Separation from an emailed report Separate when the enrolled phone is independently controlled Same destination when code and report use one mailbox
New contact-data lifecycle Phone enrollment, change, removal, and recovery Existing address may already have an approved lifecycle
Capacity unit to validate Encoded message segments and retry allowance Messages, retry allowance, and sender operations
Recovery question Who may replace or regain the enrolled number? Who may regain or change the approved mailbox?
Useful audit artifact Enrollment decision, template version, channel SLO result Sender configuration, template version, channel SLO result

The compliance record should explain why the selected destination counts as controlled, who can change it, what operational measurement supports the SLO, and when the decision expires for review. It should not preserve the submitted code or turn full contact details into convenient log correlation keys. Retention duration and investigator access depend on the institution's obligations, so the architecture should allow those policies to be set deliberately instead of smuggling them into application log retention.

This is also where “easy” becomes a serious engineering term. The easiest first API call can produce the hardest recovery process. Count enrollment changes, accessibility needs, support ownership, regional operations, abuse review, and evidence retrieval as implementation work; otherwise the comparison rewards a demo and sends the rest to on-call.

On-call ownership determines degradation cost

A safe fallback is a policy decision, not an automatic switch to whichever channel is currently fast. Sending an email code after an SMS delay can change the factor boundary, especially when that mailbox also receives the report. The runbook must say whether that transition is permitted, what extra verification it requires, and how it is recorded. It must also prevent two live codes on different channels from racing to authorize the same login under ambiguous rules.

For the report-release window, define a small state machine: create one challenge under a selected policy, allow only the configured repeat-send behavior, complete it once, and make recovery a distinct flow. Keep attachment release unavailable until the challenge reaches its valid terminal state. If transport demand exceeds its planned budget, shed new sends predictably and present recovery according to policy; don't extend expiration indefinitely or bypass the factor to drain the queue.

The preventative review should cover four failure domains in one sitting: a release wave above forecast, a regional transport slowdown, a user who no longer controls the destination, and attachment generation running behind schedule. For each, ask which queue grows, which SLO burns, which evidence is emitted, and which operator is authorized to act. A long answer here is healthy — vague ownership is what converts an ordinary delivery problem into a security exception during the busiest hour.

There are clear cases where this approach does not apply. Stick with an existing approved identity system when it already owns factor enrollment, recovery, login policy, and the evidence required for report access; duplicating that policy in the report service adds another authority. SMS-first is not suitable when stable phone access cannot be assumed or the team cannot operate number recovery and regional delivery within its SLO. Email-first is not suitable when the mailbox receives both the code and the sensitive report but the required control must be independent of that mailbox.

Cost follows on-call ownership

The platform team should own the decision model even when it buys transport. The selection is less about unit price than about who carries the recurring work and who can produce evidence after a release wave.

Layer Default ownership Reason to reverse it
Factor policy and recovery Existing approved identity owner, or the platform team Another approved system already owns the complete control
Challenge state The policy owner A managed identity service owns the same state and evidence
SMS or email transport Buy behind a narrow adapter Build only when the team can own delivery operations and abuse response
Report generation and release The education application A document system already enforces the same authorization decision

For cost, compare the complete operating envelope: expected message or segment volume, allowed repeated sends, engineering time, compliance review, support, and on-call load. Your mileage may vary by region and audience, which is why a universal “cheapest” answer isn't credible. For lock-in, keep transport-specific event shapes behind an adapter, but don't pretend policy is portable if destination enrollment and recovery semantics change with the provider.

My decision rule is conservative: use SMS when independently enrolled phone control is required and supportable; use email when the approved mailbox is the intended boundary and adding phone data would create more risk than separation; use an existing approved factor when it already carries the policy. Then prove the chosen path under the actual report-release load and preserve the model, template version, SLO result, and recovery decision as compliance evidence.

Sources

Top comments (0)