Home Projects Portfolio Dashboard Export PDF Log in

Implementing Endpoint-Level Balancing in the NJ Dialer Routing Service

In the nj-dialer-routing-service, we have recently introduced a more granular approach to call routing by implementing endpoint-level balancing. Previously, the system relied on a scalar sip_endpoint to handle outbound calls once a provider was selected. This approach was sufficient for simple setups but lacked the flexibility required for high-availability traffic management.

The Challenge

Routing engines often deal with multiple SIP gateways per provider. Relying on a single endpoint creates a bottleneck and prevents effective failover or traffic distribution across available infrastructure. Our goal was to expose more granular control, allowing the system to intelligently select the best gateway based on priority tiers and weighted balancing strategies without breaking backward compatibility.

Technical Implementation

The new implementation introduces two primary balancing strategies, both namespaced under endpoint_ to differentiate them from provider-level policies:

  1. endpoint_priority_failover: The default strategy, which maintains parity with the legacy system by prioritizing the primary gateway and failing over only when necessary.
  2. endpoint_sticky_weighted: A more advanced strategy that distributes traffic across gateways in the top priority tier, while using sticky routing based on a combination of tenant, destination, and provider IDs.

To ensure zero-downtime integration, we gated these changes behind an ENDPOINT_BALANCING_ENABLED flag. When disabled, the service falls back to the legacy scalar path, ensuring that existing configurations remain byte-identical to previous deployments.

Illustrative Example

While the internal logic handles complex balancing, the routing structure roughly follows this pattern when processing a call request:

func SelectEndpoint(ctx context.Context, req RoutingRequest, balancer Balancer) Endpoint {
    if !config.IsEnabled("ENDPOINT_BALANCING_ENABLED") {
        return req.DefaultEndpoint
    }

    switch balancer.Strategy {
    case "endpoint_sticky_weighted":
        return balancer.SelectStickyWeighted(req)
    default:
        return balancer.SelectPriorityFailover(req)
    }
}

Conclusion

By moving from a single scalar endpoint to a collection of endpoints with specific balancing logic, we have significantly improved the resiliency of our routing service. Developers can now opt-in to these strategies to better distribute load across their SIP infrastructure, ensuring higher reliability for end-users.

Implementing Endpoint-Level Balancing in the NJ Dialer Routing Service
Gerardo Ruiz

Gerardo Ruiz

Author

Share: