{
  "id": 17609963,
  "title": "Enforcing maximum concurrent SIP calls without race conditions",
  "url": "https://urgent.news/2026/11/01/enforcing-maximum-concurrent-sip-calls-without-race-conditions",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-11-01T13:50:10.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/rokasr/enforcing-maximum-concurrent-sip-calls-without-race-conditions-i1o"
  },
  "original_language": "en",
  "account": "To avoid violating the maximum number of simultaneous SIP calls without causing race conditions, capacity checks and claims must happen within a single atomic database transaction. Examine the logs of capacity readings and claims separately. If they are not aligned, it indicates a race condition allowing workers to concurrently read the safe count, write their own claim, and surpass the limit. For scheduled calls, instead of checking the capacity at a single point in time, calculate capacity over a grid of time slots spanning the call's estimated duration. Admit the call against the time slot with the least available capacity rather than the current count. If your SIP trunk carrier rejects outbound calls due to exceeding licensed channel capacity, logs will show two dispatch workers simultaneously checking the capacity limit, passing the check, and dialing calls at the same time. Despite the capacity count appearing safe at dispatch, the call still breaches the limit later. This issue stems from two bugs: a read-write race condition and treating a scheduled call as an instantaneous event. In a correctly functioning system, the capacity read and write timestamps should be identical. If they are slightly apart, it signifies a read-modify-write gap where another worker can slip in. Plot the estimated durations of admitted calls on a timeline. The peak concurrency should align with your point-in-time metrics; otherwise, the admission logic overlooks call duration. Rejections from your carrier will cluster during periods of overlapping long calls, not right at the beginning of a busy minute. I developed an admission control system to prevent such breaches by handling capacity at the application layer within a single atomic transaction. The transaction re-reads the capacity configuration and live sessions only after opening. Capacity is projected over a grid of five-minute slots covering the call's estimated duration. A call is accepted only if it passes the capacity check across all overlapping slots. This system enforces both global and per-number capacity limits simultaneously. To prevent deadlocks and retries, admissions per capacity pool are serialized using an exclusive lock in the database. When a dispatcher seeks to place a call, it acquires the lock for that specific pool, ensuring no interference between pools. If carrier capacity rejections align with simultaneous dispatch bursts, it rules out a read-write race condition. Comparing trunk occupancy metrics at dispatch time versus ten minutes later reveals whether the issue is outside the atomic transaction. If failures are limited to a single phone number, it points to a global trunk exhaustion issue rather than a targeted rate limit.",
  "summary": "By Rokas Remeika. Published 18 October 2026. To prevent concurrent workers from overcommitting a SIP trunk, capacity checks and claims must occur inside the same atomic database transaction. Reading a live-session count and writing a claim in separate steps allows workers to interleave and breach the limit. For scheduled calls, point-in-time checks fail because calls occupy time, not just an…",
  "key_points": [],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}