NYSE: IDT
Stay ahead with IDT Express
Products

Discover how our products can revolutionize the way you communicate and collaborate.

Voice

Explore our advanced voice solutions designed to optimize your communication workflows.

Diverse range of DID number solutions designed to enhance your communication capabilities.

Experience unparalleled communication efficiency with our advanced SIP Trunking Solutions.

Cutting-edge technology to proactively detect and neutralize spam flags on your DID Numbers.

Enable your customers to connect with your business by dialing a toll-free number.

AI voice agents that handle calls, capture leads, and provide customer support automatically, anytime.
Messaging

Wherever your audience is, our platform ensures seamless messaging across diverse channels.

Build customer journeys by fostering interactive conversations, all within the framework of your app. 

Connect with your audience in a simple and effective way through our cutting-edge SMS platform. 

BYOC

Harness the power of IDT as your chosen carrier while leveraging your platform’s advanced features and services.

Integrate Twilio with our robust carrier routing platform to achieve unparalleled Voice termination system.

Experience reliable and high-quality communication services while leveraging the advanced capabilities of Genesys. 

Integrate IDT with the collaborative strength of MS Teams, unlocking efficient and feature-rich communication. 

Experience the power of our carrier network seamlessly connected to Plivo through our cutting-edge BYOC solution. 

Tools

Experience the power of our online voice tools, designed to simplify communication management. 

Ensure the authenticity and integrity of outbound calls with our STIR/SHAKEN Verification Check tool. 

User-friendly tool to verify the reputation of your business number, ensuring that it remains trusted. 

Compare and gain insights into outbound call expenses, optimize budget, and make informed decisions. 

Easily estimate and compare the costs associated with different DID numbers providers. 

Compare inbound VoIP rates among top CPaaS providers and optimize your inbound call costs. 

Generate custom SMS templates. 

Resources

Empower yourself with the resources you need to thrive in the dynamic landscape of communication.

Articles covering a wide range of topics.

Discover our video guides.

Get answers to common queries.

Find instructions to make the most of our products.

Stay informed with today's most important news stories

Discover telecom insights and trends.

Find definitions of popular telecom terms.

Discover the upcoming events on our calendar
Company

A global telecom partner built to meet your needs. 

Discover the story behind our commitment to delivering innovative solutions to connect people and businesses worldwide. 

Learn about our robust network infrastructure that spans across the globe, ensuring reliable and secure connectivity. 

Got a question, feedback, or need assistance? Our dedicated team is here to help!

Find partners or sign up for partnership programs.

NYSE: IDT
Learn / Blog

Multi-Tenant DID Inventory for ISVs: Provisioning, Pooling and Porting at Scale

|
|  8 min
|
In this article

Multi-tenant DID inventory is the full set of phone numbers a platform holds and assigns across its customer accounts: numbers bought from carriers, numbers ported in from customers, numbers waiting to be used, and numbers recently released. For a UCaaS provider or an ISV embedding voice, it’s one of the few parts of the stack where a sloppy data model turns directly into lost revenue and angry tenants.

The governing principle: a number is a stateful resource with a lifecycle, not a row with a tenant_id. It has a history, obligations attached to it, and states in which it must not be reassigned. Model the lifecycle explicitly and most inventory problems don’t happen. Model it as a foreign key and you’ll rediscover every one of them in production.

This assumes you’re building the platform side and already understand SIP and number basics.

The lifecycle

Every number moves through a small set of states. Write them down as an enum and enforce the transitions in code.

  • available: in your stock, paid for, assigned to no one.
  • reserved: held for a tenant during checkout or provisioning, with a TTL.
  • pending_regulatory: requested for a tenant, waiting on documents or approval.
  • porting_in: a tenant’s existing number being moved to you; not yet live on your network.
  • assigned: live for a tenant, routing configured.
  • porting_out: the tenant has requested a move to another provider.
  • quarantined: released by a tenant, aging before it can return to available.
  • returned: released back to the carrier; you no longer pay for it.

Illegal transitions are where bugs live. quarantined → assigned directly is a privacy incident waiting to happen. porting_out → available means you’ve resold a number another provider now controls. Enforce the graph, log every transition with a timestamp and actor, and you’ll be able to answer “who had this number on 3 March?” in one query.

A minimal data model

Something like this covers most platforms:

CREATE TABLE numbers (
  e164                 TEXT PRIMARY KEY,      -- +4420...
  country              CHAR(2)   NOT NULL,
  number_type          TEXT      NOT NULL,    -- geographic | national | mobile | toll_free
  capabilities         TEXT[]    NOT NULL,    -- {voice, sms}
  state                TEXT      NOT NULL,
  state_changed_at     TIMESTAMPTZ NOT NULL,
  tenant_id            UUID,                  -- null unless reserved/assigned/porting
  source               TEXT      NOT NULL,    -- purchased | ported_in
  provider_ref         TEXT,                  -- carrier's identifier
  regulatory_bundle_id UUID,                  -- documents this number depends on
  routing_profile_id   UUID,                  -- where calls go
  emergency_address_id UUID,                  -- where required
  reserved_until       TIMESTAMPTZ,
  quarantine_until     TIMESTAMPTZ
);

CREATE TABLE number_events (
  e164        TEXT        NOT NULL,
  from_state  TEXT,
  to_state    TEXT        NOT NULL,
  tenant_id   UUID,
  actor       TEXT        NOT NULL,
  at          TIMESTAMPTZ NOT NULL DEFAULT now()
);
Code language: PHP (php)

Two design choices matter more than they look.

Routing is a reference, not a column. Point numbers at a routing profile owned by the tenant, holding the SIP destination, failover and options. When a tenant changes their PBX endpoint, you update one profile, not 4,000 numbers.

Regulatory documents are a reference too. Many numbers in the same country will depend on the same end-user documents. When a document expires, you query every number referencing that bundle. Our DID regulatory requirements checklist covers the intake side.

Stock strategy: buffer vs on-demand

Holding stock costs money every month. Not holding it costs you time at checkout. The right answer differs by country and number type.

For number types with light requirements and fast provisioning, on-demand is fine: reserve from the carrier when the tenant checks out. For popular area codes where you sell many numbers, a small buffer makes the experience instant. A simple sizing rule for a buffer: provisioning lead time in days × average daily consumption for that area code, plus a margin. If lead time is one day and you sell three numbers a day in an area code, a buffer of five or six is plenty.

For number types that require end-user documents before assignment, buffering often isn’t possible at all, because the number can’t be allocated until the specific end user is approved. Don’t build a UI that implies instant availability for those. Route the order into pending_regulatory and show the status.

Call tracking platforms have their own sizing math, since they need large pools per client; see our guide to sizing a call tracking number pool.

Reservation must be idempotent

Checkout flows retry. Users double-click. Network calls time out after the server has already acted. If “reserve number” isn’t idempotent, you’ll assign the same number twice or leak reservations that never expire.

The pattern that holds up:

  1. The client sends a reservation request with an idempotency key.
  2. The server atomically moves one available number to reserved with reserved_until = now() + TTL, keyed to that request.
  3. A retry with the same key returns the same number.
  4. Checkout commits the reservation to assigned, or it expires and a sweeper returns the number to available.

Use a single atomic update with a WHERE state = ‘available’ guard, or a SELECT … FOR UPDATE SKIP LOCKED if you’re picking from a set. Don’t read-then-write in two statements.

Release and aging

When a tenant releases a number, it doesn’t go straight back into stock. It goes into quarantine first.

The reason is practical. The number’s previous owner’s customers, contacts and automated systems will keep calling and texting it for a while. If you reassign it immediately, the new tenant receives calls meant for the old one, and some of those calls may contain information the new tenant should never hear. Aging gives that traffic time to die down.

Pick a quarantine period and watch inbound traffic on quarantined numbers. If a number is still receiving meaningful traffic at the end of the period, extend its quarantine or return it to the carrier rather than reassign it. Numbers that were heavily used, such as a main business line, deserve longer aging than a number that barely rang.

Decide, too, when to return numbers to the carrier instead of re-stocking them. A quarantined number in an area code where you have plenty of stock is just a monthly cost.

Porting in and porting out

Tenants arrive with existing numbers, and eventually some of them leave with numbers too. Both directions need first-class support.

Porting in is part of onboarding for most business customers. Model it as a state, not a background task, so the tenant can see progress and your routing is ready the moment the port completes. Our guide to porting numbers with LOA and FOC covers the paperwork and timelines.

Porting out happens when a tenant moves to another provider. Don’t block legitimate port-out requests or slow them to retain a customer; that’s a fast way to damage trust and, in many places, runs against the rules. Do verify requests properly, because fraudulent port-outs are a known attack. When a port-out completes, move the number to returned, never back to available.

Capabilities: voice and SMS are not the same number

A number’s capabilities are part of its record, and they vary. Some numbers support voice only, some voice and SMS, and SMS on some number types requires separate registration.

In the US, sending application-to-person SMS from local numbers generally requires 10DLC brand and campaign registration, which is per tenant, not per platform. If your tenants text from the numbers you assign, registration status belongs in your model alongside the number. Our 10DLC registration guide walks through the process.

Emergency calling data

For platforms offering outbound calling in the US, emergency calling isn’t optional. Interconnected VoIP services must support 911, and rules require passing a dispatchable location so responders can find the caller. Other countries have their own requirements.

In the data model, that means an emergency address linked to the number or, better, to the endpoint or user making the call, with a way for tenants to keep it current. Get legal advice for the markets you serve. The engineering point is simple: if the address isn’t in your model, you can’t send it.

Cost attribution per tenant

Every number costs you something monthly, and many carry per-minute charges on top. If you can’t attribute those costs to tenants, you can’t price accurately or spot unprofitable accounts.

Store the monthly cost and the carrier’s rate plan reference on each number, and roll costs up by tenant from the state history, not from a snapshot. A number that moved from one tenant to quarantine mid-month should be billed to the right place for the right days. Quarantined and available stock are your costs, not any tenant’s, so report them separately; a growing quarantine or buffer is an inventory decision to review, not overhead to spread across customers.

Per-minute inbound charges belong in the same model. Tag CDRs with the tenant from the number’s state at call time, so a port or reassignment during the month doesn’t misallocate usage.

Reconcile nightly

Your database and your carrier’s inventory will drift. A port completes on the carrier side but your webhook fails. A number is returned by one of your ops staff through the carrier portal. A reservation sweeper crashes.

Run a nightly reconciliation: every number the carrier bills you for should exist in your table in a paid state, and every number you think you hold should exist on the carrier side. Alert on differences. The most common finding is numbers you’re paying for that nobody is using, which is money you can recover the same day.

Where the carrier fits

Everything above is your platform’s responsibility, but it’s easier when your supply is concentrated. Each additional number provider adds another inventory feed to reconcile, another set of regulatory formats and another porting process.

IDT Express provides DID numbers in 140+ countries, so a platform can source most of its international inventory through one relationship. If you’re building for AI voice use cases, our post on DID strategy for AI receptionist platforms looks at the tenant-number question from that angle, and the DID number pillar guide ties the cluster together.

Frequently asked questions

How should a UCaaS platform manage phone numbers across customers?

Model each number as a resource with explicit lifecycle states, such as available, reserved, assigned, quarantined and porting, and enforce which transitions are allowed. Link numbers to tenant routing profiles and regulatory documents by reference rather than storing that data on each number.

What is number aging or quarantine?

Number aging is holding a released phone number out of circulation for a period before reassigning it, so calls and messages meant for the previous owner stop arriving. It protects both the new owner’s experience and the previous owner’s privacy.

Should ISVs keep a buffer of DID numbers in stock?

For popular area codes with light regulatory requirements, a small buffer sized to provisioning lead time and daily consumption makes checkout instant. For number types that need end-user documents before assignment, buffering usually isn’t possible.

How do I prevent assigning the same phone number to two customers?

Make number reservation idempotent, using an idempotency key and a single atomic state change from available to reserved with an expiry. Retries then return the same number, and expired reservations are swept back into stock.

Why reconcile number inventory with the carrier?

Your records and the carrier’s inventory drift over time because of failed webhooks, manual changes and completed ports. A regular reconciliation finds numbers you’re paying for but not using, and numbers you think you hold but don’t.

Talk to our numbers team

Building number management into your platform? Talk to the IDT Express numbers team about sourcing DID inventory across your markets.

Share this article

Leave a Reply

Required fields are marked *

Rate this article


Tags

Meet our wholesale voice routing

Fulfill all your voice calling needs with our category leading wholesale A-Z Voice Termination.
Try IDT Express for a $25 Credit

Get $25 Free Trial Credit

Get IDT Express articles in your inbox

The best source of information in the telecom industry. Join us.

    Most Popular

    porting-customer-numbers-in
    |
    |  7 min
    Porting a number in means moving an existing phone number...
    number-rotation-is-hurting-your-outbound-program
    |
    |  7 min
    Number rotation gets sold as the fix for spam labels....
    local-did-vs-toll-free-for-customer-support
    |
    |  7 min
    A toll-free number tells your customers you’ll pay for their...