DEV Community

Jason Shouldice
Jason Shouldice

Posted on • Edited on • Originally published at vicistack.com

Running Multiple Clients on One VICIdial Instance: A BPO's Isolation Guide

You run a BPO. Three clients. Client A needs 30 agents on insurance leads. Client B needs 15 doing appointment setting. Client C needs 50 on a political survey. All three expect total isolation -- their leads are confidential, their recordings are privileged, their performance data is proprietary. Running three separate VICIdial installations would triple your server costs and management overhead.

VICIdial handles this. Not perfectly -- the multi-tenancy is administrative rather than database-level -- but well enough that thousands of BPOs worldwide run multiple clients on shared instances. The key is understanding what VICIdial can and can't isolate, and configuring it so Client A never sees Client B's data.

The Architecture You're Working With

VICIdial was not designed from the ground up as a multi-tenant platform. It was designed as a single-organization dialer that gained multi-tenancy through its permission system. This distinction matters because it defines the boundaries.

What Multi-Tenancy Means in VICIdial

Three pillars:

  1. User Groups -- Every user belongs to a group that controls which admin screens, reports, campaigns, and recordings they can access.
  2. Campaign Assignment -- Campaigns are associated with user groups via allowed_campaigns. Users only see campaigns their group permits.
  3. Permission Granularity -- Dozens of fine-grained permissions covering admin screens, report types, and operational capabilities.

What Multi-Tenancy Does NOT Mean

  • No database-level isolation. All tenants share the same MySQL asterisk database. Client A's leads sit in the same vicidial_list table as Client B's. Differentiated by list_id and campaign_id, not separate databases.
  • No Asterisk-level isolation. Shared SIP channels, conference bridges, recording resources.
  • No OS-level isolation. No containers, no VMs, no process separation.

The isolation is enforced at the application layer through the admin interface. A user with direct MySQL or SSH access can see all tenants' data. For most BPOs this is fine -- clients see VICIdial through the admin UI and the reports you provide.

For clients with contractual requirements for database-level isolation (HIPAA, SOC 2, government), you need separate VICIdial instances.

User Group Configuration

User groups are the foundation. Every client gets their own groups, and permissions determine exactly what they see.

Creating Client Groups

Group ID Users Admin Level Purpose
CLIENT_A_ADMIN Managers 7 Run reports, configure campaigns
CLIENT_A_AGENT Agents 1 Log in, take calls, disposition
CLIENT_B_ADMIN Managers 7 Same but restricted to Client B
CLIENT_B_AGENT Agents 1 Same
BPO_ADMIN Internal team 9 Full access to everything

Why separate ADMIN and AGENT groups? Managers need report access. Agents need to log in and take calls. Different permission levels.

The Critical Setting: Allowed Campaigns

In the user group config, the Allowed Campaigns field lists which campaigns users in this group can see. This is the most important setting for tenant isolation.

Allowed Campaigns: CLIENT_A_SALES CLIENT_A_SURVEY CLIENT_A_INBOUND
Enter fullscreen mode Exit fullscreen mode

Users only see these campaigns in admin, agent login, and reports. All other campaigns are invisible.

Important: Must be manually updated when you create or remove campaigns for a client. Forgetting to add a new campaign means the client can't see it. Forgetting to remove a reassigned campaign means data leakage.

Admin Screen Permissions

For a client manager group:

Permission Recommended Notes
Admin Access 7 or 8 Never 9 for clients
Campaigns View only Or Modify for trusted clients
Lists View and Modify Clients upload their own leads
Users View Can see their agents
Carriers NONE Never expose trunk config
DIDs View only Can see their assigned numbers
Servers NONE No infrastructure visibility
System Settings NONE Never
User Groups NONE Never

Recording Access

Setting Client Manager Client Agent
Recording Access ALL OWN or NONE
Allowed Recording Campaigns Their campaigns only Their campaigns only

Client managers listen to any recording from their campaigns but can't access other clients'. Agents hear only their own calls (for self-improvement) or nothing.

Campaign Isolation and Naming

Use consistent naming that includes the client identifier:

CLIENT_A_SALES_OB     (Client A outbound sales)
CLIENT_A_INBOUND      (Client A inbound)
CLIENT_B_APPT_SET     (Client B appointment setting)
Enter fullscreen mode Exit fullscreen mode

This makes administration clearer and per-client billing queries straightforward.

List Organization

Assign list ID ranges per client:

Client Range Example
Client A 1000-1999 1001 = Client A Fresh Insurance Leads
Client B 2000-2999 2001 = Client B Appointment Leads March
Client C 3000-3999 3001 = Client C Voter File Q1
Internal/Test 9000-9999 9001 = Internal Test List

Not enforced by VICIdial -- it's organizational discipline. But it makes auditing visually obvious.

Data Leakage Vectors

Vector 1: Campaigns in wrong user group. Double-check Allowed Campaigns when adding or removing campaigns. Quarterly audit.

Vector 2: Lists assigned to wrong campaigns. Client A's list accidentally on Client B's campaign = Client B's agents dial Client A's leads. Audit list-to-campaign assignments monthly.

Vector 3: Direct database access. If a client has any MySQL access for custom reporting, they could query vicidial_list and see everything. Mitigate with MySQL views:

CREATE VIEW client_a_leads AS
SELECT * FROM vicidial_list WHERE list_id BETWEEN 1000 AND 1999;
GRANT SELECT ON asterisk.client_a_leads TO 'client_a_report'@'%';
Enter fullscreen mode Exit fullscreen mode

Vector 4: Real-time report. Log in as a client user and verify they only see their own agents.

SIP Trunk Allocation

Three strategies:

Strategy 1: Shared Trunk Pool

All clients share trunks. Simplest. Cheapest. Highest utilization -- idle capacity from one client automatically available to another. But one client's spike can starve another, caller ID management is more complex, and a carrier outage hits everyone.

Strategy 2: Dedicated Per Client

Separate carrier entries per client. Complete isolation, clean cost attribution. Higher cost because each client pays for idle capacity. More configuration work.

Strategy 3: Hybrid

Dedicated primary trunk per client with a shared overflow pool. Guaranteed capacity for each client, overflow prevents busy signals during spikes. Most complex to configure.

Rule of thumb: Small clients (<10 agents) share trunks. Medium (10-50) get dedicated trunks -- enough volume to justify their own allocation, and they typically have caller ID and compliance requirements. Large (50+ agents) get dedicated trunks and possibly their own VICIdial instance.

Per-Tenant Billing

Most BPOs bill on agent hours, call minutes, or a combination. VICIdial provides the raw data for any model. Track agent hours by user group, outbound minutes by campaign, inbound minutes by inbound group, and recording storage by campaign.

Automate monthly billing reports with a script that runs on the 1st, querying vicidial_log and vicidial_agent_log filtered by campaign and date range. Map campaigns to clients and generate per-client summaries.

Capacity Planning for Multi-Tenant

Server Sizing

Total Agents Configuration
Under 25 Single server, all roles
25-75 Web + DB server, separate telephony
75-150 Web, DB, 2-3 telephony servers
150-300 Full cluster with redundancy
300+ Consider separate instances

Add 20-30% buffer over single-tenant sizing for multi-tenant overhead.

Concurrent Call Capacity

Each outbound agent with predictive dialing at 3:1 ratio generates 3 concurrent SIP channels plus inbound:

  • Client A: 30 agents x 3 = 90 + 10 inbound = 100 channels
  • Client B: 15 agents x 2 = 30 + 5 inbound = 35 channels
  • Client C: 50 agents x 4 = 200 + 0 inbound = 200 channels
  • Total: 335 concurrent channels

Each Asterisk server on modern hardware handles 250-350 concurrent channels with recording active. This three-client scenario needs at least 2 telephony servers.

Noisy Neighbor Problems

One client's traffic spike degrades others. Mitigations:

  • CPU contention from AMD processing: Monitor per-campaign channel usage
  • Hopper contention: Large lists fill the hopper slower and delay other campaigns. Stagger hopper levels.
  • Recording I/O: 200 concurrent recordings write ~200 MB/minute. Use separate disks for recordings vs database.

Limitations to Be Honest About

No per-tenant resource guarantees. VICIdial has no resource quotas or QoS at the tenant level. First-come-first-served. Overprovision (run at 60-70% capacity) to mitigate.

Shared system settings. Recording format, session timeouts, API controls, timezone settings -- all global. You can't have Client A on WAV and Client B on MP3.

Admin level 9 sees everything. Operationally required but may concern clients wanting absolute isolation. Limit level 9 to a small number of trusted administrators.

When to Split

Signals you need separate instances:

  • Client requires database-level isolation (regulatory or contractual)
  • Client has 100+ agents impacting other tenants
  • Client needs custom VICIdial modifications
  • Client needs different Asterisk or VICIdial versions
  • Client demands dedicated infrastructure contractually

The cost trade-off: shared instance for 3 clients = $200-500/month total. Dedicated instances = $200-500/month per client plus 3x administration. The hybrid approach most BPOs land on: large anchor clients get dedicated instances, medium clients share with 2-3 similar-sized clients, small clients share a multi-tenant instance with 5-10 others.

DID Routing Per Tenant

Most BPO clients have their own inbound phone numbers that route to specific campaigns and inbound groups.

For each client with inbound:

  1. Navigate to Admin > Inbound Groups and create a group: CLIENT_A_INBOUND
  2. Navigate to Admin > DIDs and create entries for the client's numbers, routing to their inbound group
  3. Set call times, queue priority, and after-hours routing per client

Per-Client IVR

Each client wants their own greeting and menu structure. Create separate call menus per client with custom audio, then route each option to the client-specific inbound group.

Track DID inventory by client for accurate billing. Which DIDs belong to which client, what's the monthly carrier cost per DID, and are any DIDs unused.

Example: Complete 3-Client BPO Configuration

Clients: Apex Insurance (25 OB + 5 IB agents), GreenSolar (15 OB agents), VoteReach (40 OB agents, seasonal)

User Groups

Group Users Level Allowed Campaigns
BPO_SUPER 2 super admins 9 All
BPO_MANAGER 4 managers 8 All
APEX_MANAGER 2 7 APEX_OB_SALES, APEX_INBOUND
APEX_AGENT 30 1 APEX_OB_SALES, APEX_INBOUND
GREEN_MANAGER 1 7 GREEN_APPTSET
GREEN_AGENT 15 1 GREEN_APPTSET
VOTE_MANAGER 2 7 VOTE_SURVEY_Q1
VOTE_AGENT 40 1 VOTE_SURVEY_Q1

Campaigns

Campaign Client Lists Carrier
APEX_OB_SALES Apex 1001-1050 APEX_SIP (dedicated)
APEX_INBOUND Apex N/A APEX_SIP
GREEN_APPTSET GreenSolar 2001-2020 SHARED_POOL
VOTE_SURVEY_Q1 VoteReach 3001-3100 SHARED_POOL

Infrastructure

Server Spec Role
Server 1 8-core, 32 GB, 2 TB SSD DB + Web
Server 2 8-core, 16 GB, 1 TB SSD Telephony (Apex + Green)
Server 3 8-core, 16 GB, 1 TB SSD Telephony (VoteReach, seasonal)

Server 3 can be decommissioned when VoteReach's seasonal campaign ends, reducing costs during off-peak.

FAQ: The Questions Every BPO Asks

Can an agent work across multiple clients? Yes, but it breaks isolation. If an agent's group has access to both Client A and Client B campaigns, they could see data from both. Create a separate cross-client group and understand the trade-off.

Per-client DNC lists? Use per-campaign DNC (Admin > Campaigns > DNC settings). A number DNC for Client A isn't automatically DNC for Client B. The system-wide DNC applies globally -- use it for numbers that should be blocked for everyone.

Can clients manage their own campaigns? With level 7-8 and campaign modify permissions limited to their allowed campaigns, they can adjust dial levels, recycling, and dispositions. Start with read-only, upgrade as the client proves competent.

Per-client trunk limits? VICIdial doesn't have built-in per-campaign trunk limits. Limit the max dial level on a client's campaign to indirectly cap concurrent trunk usage. 20 agents x dial level 3.0 = max 60 outbound channels.

Branding the agent interface? Not natively -- same agent screen for all groups. Use campaign-level scripts to display client-specific logos and content in the script panel. For fully separate branded interfaces, build custom agent screens using VICIdial's agent API.

Client onboarding? Create user groups, campaigns, lists, carrier entries (if dedicated), DID routing. Assign list ID ranges. Create users. Test with a small pilot list.

Client offboarding? Export data (leads, CDR, recordings). Deactivate campaigns, users, groups -- don't delete (billing disputes, compliance). Archive recordings. Hold DIDs 30-90 days in case client returns.

ViciStack builds multi-tenant VICIdial deployments for BPOs with proper isolation, per-client reporting, and scalable infrastructure that grows with your client roster.

Originally published at https://vicistack.com/blog/vicidial-multi-tenant/

Top comments (0)