vicigeeksimple guides
Browse
All guides

Running your system · Growth signals, measured not guessed

When to outgrow VICIdial: test the requirement before deciding

Build an evidence record for the actual unmet requirement, compare a bounded improvement with a managed alternative, and test the workflow on both. VICIdial has native chat and inbound email; channel names alone do not establish feature fit.

Reader setup

Before you choose

  1. One concrete failed or costly workflow with timestamps, scope and an owner.
  2. Access to configuration/measurement owners; use Create a read-only database account for safe VICIdial queries for optional SQL.
  3. Equivalent requirements and a current candidate offer for the migration comparison.
Expected result
A filled stay/improve/migrate decision with tested requirements, costs, unknowns and a next acceptance test.
Before making changes
No production change, index creation, port expansion or migration is prescribed by a symptom. Read-only probes can expose internal details; keep actual records private.

Start with the symptom and a measurement

Start with a falsifiable requirement: for example, “an authorized agent must receive this email, reply under the right identity and produce the required audit trail.” “We need omnichannel” is too broad to compare or test.

Keep three possible conclusions open: the existing deployment already supports the task; a bounded improvement can satisfy it; or a candidate platform satisfies an important requirement the current arrangement cannot meet at an acceptable cost.

You should seeThe requirement names an actor, an input, an observable outcome and the conditions under which it must hold.

  • Write one mandatory workflow and the evidence needed to accept it.
  • Separate a feature gap from an implementation, staffing or support gap.
  • Keep improve, retain and migrate as testable options until the comparison is complete.
Trace path · read left to right
01Name the unmet workflow02Test the specific limitation03Compare equivalent outcomes and ownership

Separate the symptom, hypothesis and acceptance test

A busy-hour failure is an observation. Port exhaustion, a slow query, carrier throttling and agent availability are competing explanations. Write down the evidence needed to distinguish them before selecting a change.

Before you use it
This is an original fictional example, not a product endorsement or a measured deployment.
Fictional requirement record
Requirement: after-hours inbound email gets a tracked response within the agreed window.Current observation: feature exists, but no support owner covers the window.Candidate A: keep VICIdial + add a named operating/support contract.Candidate B: managed platform + verify support scope and routing workflow.Acceptance: send an approved synthetic email after hours; verify routing, response identity, timestamps and exportable history.Decision today: pending quotes and two complete workflow tests.
Not executed · worksheet or reference text

This sample is a template or reading aid, not a terminal command. There is no output to show.

Success looks like
The test distinguishes missing operations coverage from an absent software feature.
Stop if
Do not choose a platform while the mandatory workflow, contract coverage or cost is unknown.
  • Record the symptom, time window, affected users and competing explanations.
  • Name the observation that would support or reject each explanation.
  • Leave unmeasured constraints unknown; a familiar symptom does not prove the cause.

Test media allocation and network behavior before naming a ceiling

A configured RTP range, a firewall rule and a current channel count are different observations. None alone measures allocated media sockets, packet loss or the busiest interval. Compare synchronized media/network telemetry with the actual affected call paths.

If the evidence identifies a constrained allocation or blocked path, plan a scoped change and its retest with the owner. If it does not, keep investigating. A large-looking unused range does not rule out NAT, addressing or packet-loss problems.

firewall-cmd --info-service=rtp prints a service definition. It does not show that the service is enabled in an active zone, or that the actual Asterisk range is permitted. Compare the loaded range with the relevant runtime zone and all applicable policy/provider rules; test the authorized media path separately. Do not reload or open a range as a diagnostic shortcut.

Before you use it
Use the approved root/read-only CLI context. Keep source ranges and firewall output private. Includes/defaults may supply the RTP range if this file has no active assignments.
Read configured RTP range and active firewalld context
grep -nE '^[[:space:]]*(rtpstart|rtpend)[[:space:]]*=' /etc/asterisk/rtp.confif command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state; then  firewall-cmd --get-active-zones  printf '%s\n' 'Next: replace ACTUAL_ZONE with the interface/source zone above.'  printf '%s\n' 'Read: firewall-cmd --zone=ACTUAL_ZONE --list-all'else  printf '%s\n' 'STOP: identify the actual firewall backend and its owner; no allowance is established.'fiasterisk -rx 'core show channels count'
Reader-run example · not executed for this guide

This example has no recorded result here. Follow its preparation, expected result and stop conditions before using it.

Success looks like
You have the configured range, actual active zone/interface/source bindings and a call-count snapshot. Read the named zone with --list-all and have the network owner include applicable policies/direct/nftables rules and provider controls.
Stop if
A service definition, empty grep or one zone listing is not an allow verdict. Stop the capacity conclusion until the owner explains the effective rule path and the intended media test.

Measure competing account and media limits

  • Record configured, permitted and observed allocation separately.
  • Do not convert an Asterisk channel count directly into RTP-port use.
  • Retest the affected call behavior after an approved change.

Correlate workload and contention across roles

Running database, web and dialer roles on one host is a topology fact, not a diagnosis. Measure the affected interval: CPU, storage latency, query duration, memory pressure, calls and scheduled jobs. Use a controlled comparison to establish contention.

The monthly row-count query below describes retained campaign log volume. It does not measure storage latency or prove that retention caused the incident. An archival or role-separation plan needs a recoverable copy and a task-specific acceptance test.

Before you use it
Run this read-only outside busy hours for one test campaign. It groups retained call rows by month; it does not measure total table growth.
Measure your own table growth before assuming a ceiling
SELECT DATE_FORMAT(call_date, '%Y-%m') AS call_month, COUNT(*) AS call_rowsFROM vicidial_logWHERE campaign_id = '<CAMPAIGN_ID>'  AND call_date >= DATE_SUB(NOW(), INTERVAL 6 MONTH)GROUP BY call_monthORDER BY call_month;
Evidence · ViciBox 12 demo capture · demo values substituted

Captured demo response · 2026-09-24 22:25 UTC. Any filtering, hidden values or test-only data are identified in the capture label. Select Replay transcript to read the recorded output.

Command output line: SELECT DATE_FORMAT(call_date, '%Y-%m') AS call_month, COUNT(*) AS call_rows FROM vicidial_log WHERE campaign_id = 'KPISYN1' AND call_date >= DATE_SUB(NOW(), INTERVAL 6 MONTH) GROUP BY call_month ORDER BY call_month;
(no output)
Success looks like
The query shows retained call rows grouped by month for the selected campaign; archived or deleted rows are absent, and the result does not measure total table size.
Stop if
An empty result may mean no retained rows match the campaign and period. Check the filters and retention policy before drawing a growth conclusion.
  • Record role placement separately from measured contention.
  • Compare retained row counts with retention and archival policy.
  • Ask the responsible owner to test a proposed topology or retention change against the same workload and recovery requirement.

Inspect a slow query before changing indexes or report routing

Collect the actual slow query, its plan, table sizes and the conditions under which it is slow. Inspect existing indexes before proposing one. A missing index name is not proof that a new index helps this workload, and a populated replica setting is not proof that reports use a healthy replica.

The read-only inventory below records candidate inputs for the database owner. Measure the same report and source data before/after any separately reviewed change.

Before you use it
Run this read-only, through the approved sudo mysql --defaults-file=/etc/vicidial-readonly.cnf context after verifying SELECT CURRENT_USER(), DATABASE(), against your own install; a customized deployment can differ from the shipped schema if anyone has already added an index. The last statement reports whether slave_db_server is set rather than selecting its value, so a captured run never prints a real hostname.
Check your own indexes and report-slave configuration
SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME, SEQ_IN_INDEX FROM information_schema.STATISTICSWHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME IN ('vicidial_hopper', 'vicidial_live_agents', 'vicidial_log')ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX; SELECT COALESCE(CHAR_LENGTH(slave_db_server), 0) > 0 AS slave_db_server_is_set, reports_use_slave_dbFROM system_settingsLIMIT 1;
Evidence · ViciBox 12 demo capture

Captured demo response · 2026-09-24 22:25 UTC. Any filtering, hidden values or test-only data are identified in the capture label. Select Replay transcript to read the recorded output.

Command output line: SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME, SEQ_IN_INDEX FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME IN ('vicidial_hopper', 'vicidial_live_agents', 'vicidial_log') ORDER BY TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;
+----------------------+------------------+------------------+--------------+
| TABLE_NAME | INDEX_NAME | COLUMN_NAME | SEQ_IN_INDEX |
+----------------------+------------------+------------------+--------------+
| vicidial_hopper | lead_id | lead_id | 1 |
| vicidial_hopper | PRIMARY | hopper_id | 1 |
| vicidial_live_agents | last_call_finish | last_call_finish | 1 |
| vicidial_live_agents | last_call_time | last_call_time | 1 |
| vicidial_live_agents | last_update_time | last_update_time | 1 |
| vicidial_live_agents | PRIMARY | live_agent_id | 1 |
| vicidial_live_agents | random_id | random_id | 1 |
| vicidial_live_agents | vlali | lead_id | 1 |
| vicidial_live_agents | vlaus | user | 1 |
| vicidial_log | call_date | call_date | 1 |
| vicidial_log | lead_id | lead_id | 1 |
| vicidial_log | PRIMARY | uniqueid | 1 |
+----------------------+------------------+------------------+--------------+
Command output line: SELECT COALESCE(CHAR_LENGTH(slave_db_server), 0) > 0 AS slave_db_server_is_set, reports_use_slave_db FROM system_settings LIMIT 1;
+------------------------+----------------------+
| slave_db_server_is_set | reports_use_slave_db |
+------------------------+----------------------+
| 0 | |
+------------------------+----------------------+
Success looks like
You can see, for your own tables, whether a composite index on campaign_id together with status or call_date already exists, and whether slave_db_server_is_set is 1 or 0 and reports_use_slave_db is populated.
Stop if
A missing index or unset report-slave value is a configuration observation, not proof of the cause of slowness. Inspect query plans, workload and replica health before deciding on a change.

You should seeThe proposed database action names a query and an acceptance measurement rather than relying on a configuration flag.

  • Match proposed indexes to the actual query plan and write workload.
  • Verify report routing and replica health; configuration presence alone does not establish either.
  • Measure the affected report before and after any approved change.

Separate operational drop ratios from legal abandonment

A campaign’s logged DROP count can reveal an operational trend. Dividing it by all log rows does not produce the live-human abandonment measure described in the applicable rules. Call classification and timing need separate evidence.

Keep call mix, agent availability and measured results in the decision record. A dial-level change is not a substitute for a completed, compliant workflow.

Before you use it
Use the approved read-only session and replace <CAMPAIGN_ID>. Confirm the database timezone and that this log population matches the operational question.
Read an operational DROP share of campaign log rows
SELECT DATE_FORMAT(call_date, '%Y-%m-%d') AS call_day,       COUNT(*) AS logged_rows,       SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) AS drop_rows,       ROUND(100 * SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) / COUNT(*), 2) AS drop_share_of_log_rows_pctFROM vicidial_logWHERE campaign_id = '<CAMPAIGN_ID>'  AND call_date >= DATE_SUB(NOW(), INTERVAL 14 DAY)GROUP BY call_dayORDER BY call_day;
Reader-run example · not executed for this guide

This example has no recorded result here. Follow its preparation, expected result and stop conditions before using it.

Success looks like
The ratio is explicitly DROP rows divided by selected log rows. It is not a count of people reached or a legal abandonment finding.
Stop if
Stop interpreting the rate if live-person classification, timing or the selected population is unknown; use Predictive vs power dialing: which mode fits your team for the distinct denominator discussion.

Dial-mode and live-answer measurement distinctions

  • Name the status population and time window before calculating an operational ratio.
  • Review live-person classification and timing separately for abandonment.
  • Compare permitted trials under equivalent staffing and call-mix conditions; restore prior settings if agreed limits fail.

Use staffing counts only for the question they answer

The two queries count distinct users found in a historical log window and selected live-agent rows now. Neither calculates peak concurrent active sessions over the historical window. Treat stale rows, reconnects and campaign scope explicitly.

For license or capacity comparisons, use a reviewed session-overlap calculation or the platform’s documented peak metric. Keep named users, simultaneous sessions, channels and billed units in separate fields.

Before you use it
Run both statements read-only, through the approved sudo mysql --defaults-file=/etc/vicidial-readonly.cnf context after verifying SELECT CURRENT_USER(), DATABASE(); run the second query again during your actual busiest hour, not an average one, since a single snapshot can understate peak concurrency. This lab scopes both statements to one fixture campaign for a safe capture; on your own install, drop the campaign_id filter for an org-wide total.
Count agents in logs and one live snapshot
SELECT COUNT(DISTINCT user) AS distinct_agents_last_30_daysFROM vicidial_logWHERE campaign_id = '<CAMPAIGN_ID>'  AND call_date >= DATE_SUB(NOW(), INTERVAL 30 DAY); SELECT COUNT(*) AS agents_logged_in_right_nowFROM vicidial_live_agentsWHERE campaign_id = '<CAMPAIGN_ID>'  AND status IN ('READY','INCALL','QUEUE','PAUSED');
Evidence · ViciBox 12 demo capture · demo values substituted

Captured demo response · 2026-09-24 22:25 UTC. Any filtering, hidden values or test-only data are identified in the capture label. Select Replay transcript to read the recorded output.

Command output line: SELECT COUNT(DISTINCT user) AS distinct_agents_last_30_days FROM vicidial_log WHERE campaign_id = 'KPISYN1' AND call_date >= DATE_SUB(NOW(), INTERVAL 30 DAY);
+------------------------------+
| distinct_agents_last_30_days |
+------------------------------+
| 0 |
+------------------------------+
Command output line: SELECT COUNT(*) AS agents_logged_in_right_now FROM vicidial_live_agents WHERE campaign_id = 'KPISYN1' AND status IN ('READY','INCALL','QUEUE','PAUSED');
+----------------------------+
| agents_logged_in_right_now |
+----------------------------+
| 0 |
+----------------------------+
Success looks like
The first result is a distinct-user count over the chosen log window; the second is a point-in-time selected live-agent row count. Neither is historical peak concurrency.
Stop if
Repeat snapshots or use a time-series report to estimate the peak; compare each vendor’s definition of a licensed user before pricing.
  • Match each quoted licensing unit to the same measured quantity.
  • Use a reviewed historical overlap calculation or documented peak metric for peak concurrency.
  • Keep distinct historical users and one live snapshot separate from peak concurrent active agents.

Test the exact channel, support and evidence requirement

VICIdial documents native customer/agent chat and inbound email handling. Do not list those channel names as missing features. Instead test the required routing, identity, history, permissions, accessibility, integration and support behavior on the installed version.

A managed offer can still be a better fit if it demonstrably meets mandatory operating coverage, recovery, reporting or contractual requirements that the current arrangement cannot provide economically. A logo, feature checkbox or generic “omnichannel” claim is not that demonstration.

Compare the actual unmet requirementScroll sideways to compare columns
RequirementCurrent deployment testCandidate test
Inbound emailSynthetic intake, agent routing, reply identity, history/exportSame complete workflow and required integrations.
Customer chatEntry, routing, handoff, transcript and permissionsSame scenario, including failure and recovery.
Support and recoveryNamed owner, coverage window and demonstrated recoveryContract scope plus a reviewed recovery exercise.
Other messaging channelVerify the installed integration and required workflowVerify included channel, restrictions and ongoing responsibility.
  • Run the mandatory workflow on the current installation and candidate under comparable conditions.
  • Record actual channel behavior, integration needs and contracted support coverage.
  • Obtain a current itemized quote with assumptions, exclusions and term before comparing costs.
Sources for this section

Complete a reversible decision record

Compare the same workload, support window, retention, integrations and recovery requirement over the same period. Include migration effort, overlap operation, number changes, training, internal support time and contractual exclusions. Unknown costs remain unknown.

Write a decision with a review date and a reversal or exit condition. A trial that fails the mandatory workflow should change the conclusion even if its headline price is lower.

  1. Fill the requirement and evidence rows in the downloadable record.
  2. Complete one bounded improvement test and one equivalent candidate workflow test where feasible.
  3. Compare the total responsibility/cost scope and unresolved mandatory criteria.
  4. Choose stay, improve, migrate or defer; name the next owner and test.

You should seeThe recommendation states which requirement was met, what remains unknown and what evidence would change it.

Download the platform decision record

Compare operating responsibilities and costs

  • Document data, recording and configuration portability for every option, including the self-hosted deployment.
  • Include implementation, training, parallel operation and ongoing ownership in the comparison.
  • Set a review date, acceptance criteria and a reversible next action.

Checks and sources

What was checked

  • Native customer/agent chat and inbound email capability are supported by the official feature and chat references reviewed November 6, 2026. Presence does not establish the reader’s required channel workflow, integrations or support coverage.
  • The worked decision is fictional. No production capacity, incident-frequency or migration result is asserted; a configuration value is a hypothesis to test, not proof of the cause.

Primary references

Sources

  1. Open-source VICIdial featuresVICIdial Group · accessed November 6, 2026
  2. Customer and agent chatVICIdial · accessed November 6, 2026
  3. VICIdial PJSIP SupportVICIdial · accessed November 6, 2026
  4. SIP Trunking scale and limitsTwilio · accessed November 6, 2026
  5. firewall-cmd service and active-zone queriesfirewalld · accessed November 7, 2026

Follow without guesswork

Get the next article

RSS is live now. Email delivery below is an explicit local preview and sends nothing.Open the RSS feed
Email preview only. The address stays in this browser and is never transmitted.