Skip to content

Load Test Pipeline Synthetic Campaign Runner ​

File: client_backend/src/tests/load-test-pipeline.ts

Why ​

Integration tests prove correctness. Load tests prove your system handles real-world throughput. This script creates a synthetic campaign with N contacts and simulates the full webhook pipeline for each one at configurable concurrency no real SIP calls, no real phone numbers.

Use this to answer questions like:

  • Can the backend handle 500 concurrent webhook pipelines without data corruption?
  • How many contacts/second can we process?
  • Do credits add up correctly across hundreds of calls?
  • Are there any stuck contacts after a high-throughput run?

How To Run ​

bash
cd client_backend

# Quick smoke test (50 contacts, 10 concurrent)
npx tsx src/tests/load-test-pipeline.ts --contacts 50 --concurrency 10

# Realistic load (500 contacts, 50 concurrent)
npx tsx src/tests/load-test-pipeline.ts --contacts 500 --concurrency 50

# Heavy load with verbose output
npx tsx src/tests/load-test-pipeline.ts --contacts 1000 --concurrency 100 --verbose

# Keep test data for inspection (skip auto-cleanup)
npx tsx src/tests/load-test-pipeline.ts --contacts 100 --concurrency 20 --skip-cleanup

Options ​

FlagDefaultDescription
--contacts N100Total contacts to simulate
--concurrency N20Max parallel webhook pipelines
--verboseoffExtra logging per contact
--skip-cleanupoffDon't delete test data after run

What It Does ​

  1. Creates a test Organization, Customer, Campaign, and ServicePricing
  2. Bulk-inserts N Contact documents
  3. For each contact, simulates the full webhook pipeline based on a realistic outcome distribution:
    • 60% answered (full pipeline: join → record → leave → billing → transcription → analysis)
    • 15% rejected
    • 15% not picked
    • 5% media failure
    • 5% timeout
  4. Prints throughput metrics, outcome breakdown, billing totals, and data integrity checks
  5. Cleans up all test data (unless --skip-cleanup)

Reading The Output ​

--- Throughput ---
  Total time:          8.6s
  Contacts processed:  50/50        ← should equal total contacts
  Throughput:          5.8 contacts/sec
  Avg processing time: 1570ms per contact

--- Outcomes ---
  answered            28  (56.0%)   ← should be ~60% of total
  notPicked            9  (18.0%)
  rejected             5  (10.0%)
  ...

--- Data Integrity Check ---
  Done:           28                ← should match answered count
  Failed:         22                ← should match non-answered count
  Stuck:          0                 ← MUST be 0
  With billing:   28                ← should match done count

--- VERDICT ---
  ALL CHECKS PASSED                 ← what you want to see

Red flags:

  • Stuck > 0 contacts didn't complete the pipeline
  • Status mismatch done + failed doesn't equal total
  • Billing mismatch some answered calls weren't billed
  • Processing errors exceptions during simulation

Database ​

The load test runs against config.dbName (the main database, e.g., Oktivo-Dev), NOT a _test suffix database. It cleans up after itself unless --skip-cleanup is used.

If you use --skip-cleanup, you can validate the campaign data with:

bash
npx tsx src/scripts/validate-campaign.ts <campaignUID>

The campaign UID is printed at the end of the load test output.

Known Issues ​

  • ServicePricing legacy indexes: The collection may have legacy unique indexes using old field names (serviceType, organizationId, customerId). If you encounter E11000 duplicate key error, run POST /internal/scripts/fix-service-pricing-indexes to drop legacy indexes and clean up invalid records. See SERVICE-PRICING.md for details.
  • Mongoose disconnect can be slow on Windows the script may appear to hang for a few seconds after printing results. The test itself has already completed.

Last updated: