Phone Number Portability: Tracking Numbers Across Carriers

Navigate the complexities of phone number portability and its impact on validation, carrier detection, and user experience.

Phone Number Portability: Tracking Numbers Across Carriers
September 8, 2025
11 min read
Phone Validation

Phone Number Portability: Tracking Numbers Across Carriers


Mobile Number Portability (MNP) allows users to change carriers without changing their MSISDN. For validation and carrier tracking, this means: HLR/NP databases are mandatory, and operator prefixes are often misleading.


Phone Number Portability Overview

Phone Number Portability Overview


MNP Basics


  • Ported: number has been transferred — the original MCC/MNC prefix does not reflect the current operator.
  • Non-ported: number remains with the original operator.
  • Partial MNP: countries without centralized database — requires HLR query to the home network.

Prioritize: fast cache → local NP database → HLR/NP provider with status confirmation.


Data Sources and Standards


  • NP Registry: centralized databases (e.g., EU/some APAC countries). Response provides current operator and porting date.
  • HLR Lookup: actual subscriber status (active/inactive), current operator's MCC/MNC, possibly roaming status.
  • CRDB/ENUM (in some countries): MSISDN→routing mapping.

Best practice: update local NP cache every 24h, HLR results every 1–4h; include data version in API response.


Validation Flow and Fallbacks


type MNPInfo = { isPorted: boolean; current: { mcc: string; mnc: string; carrier: string }; portedAt?: number }

async function resolveCarrier(msisdn: string): Promise<MNPInfo> {
  const cached = await cache.get(msisdn)
  if (cached) return cached

  // 1) Fast NP database
  const np = await npRegistry.lookup(msisdn).catch(() => null)
  if (np) return save(msisdn, normalize(np))

  // 2) HLR fallback
  const hlr = await hlrProvider.lookup(msisdn, { timeoutMs: 3000 }).catch(() => null)
  if (hlr) return save(msisdn, normalize(hlr))

  // 3) Prefix as last resort (low confidence)
  const inferred = inferByPrefix(msisdn)
  return { ...inferred, isPorted: true } // mark as uncertain
}

Key point: explicitly mark confidence level and source (np|hlr|prefix) so business logic can respond appropriately.


Fraud Signals Around Porting


Porting is often used in fraud/ATO schemes:


  • Fresh Port (< 7 days): elevated risk for SMS OTP/2FA — request additional verification.
  • Frequent Ports (n transfers within 90 days): risk flag.
  • Carrier Mismatch: discrepancy between geo/payment instrument and current operator.

Recommendation: mark such cases as risk=high, request alternative verification channel (push/email/WebAuthn).


Implementation Notes


  • Number normalization: E.164, cleanup, auto-add country code on backend.
  • TTL: MNP 24h, HLR 1–4h, prefix 1h. Update on events (SMS delivery errors, user complaints).
  • Rate limits: HLR is expensive — set budget and degrade to NP/prefix.
  • API response: { isPorted, current: { mcc,mnc,carrier }, portedAt, confidence, source }.

Monitoring and SLAs


  • Metrics: % correct operators (by SMS delivery/DR), average latency, provider error rate, fresh port percentage.
  • Alerts: spike in fresh ports, OTP delivery failure, increase in HLR timeouts.
  • SLA: p95 < 400ms via cache; operator accuracy > 98% on validation deliveries.

We provide MNP/HLR enrichment for phone validation with confidence scoring and caching.

Tags:number-portabilitycarrier-switchingmnpvalidation-challenges