Optimizing Inbound Service Through Denormalized Cache Strategies
In the nj-dialer-inbound-service project, we recently focused on reducing latency for our core DID (Direct Inward Dialing) lookup operations. By re-evaluating our data access patterns, we identified a bottleneck caused by unnecessary joins and secondary service lookups when retrieving flow configurations associated with incoming numbers.
The Problem: Multi-Stage Lookups
Previously, fetching the routing details for a DID required a two-step process: querying the DID registry, followed by hydrating the associated flow graph from a secondary cache or downstream service. In high-concurrency environments managed via Kubernetes, this added significant latency and increased the potential for partial failures during spike periods.
The Solution: Denormalization
We moved to a denormalized cache strategy. By embedding the flow graph directly into the DID payload within Redis, we transformed a complex multi-step dependency into a single, atomic O(1) lookup. This eliminates the need for the FlowHydrator and secondary internal calls, significantly flattening our request lifecycle.
Implementation Example
Our Go-based service now handles these lookups as a unified operation:
type DIDPayload struct {
Number string `json:"number"`
Flow FlowGraph `json:"flow"`
Active bool `json:"active"`
}
// FetchDID serves the payload directly from Redis
func FetchDID(ctx context.Context, number string) (*DIDPayload, error) {
data, err := redisClient.Get(ctx, "did:" + number).Result()
if err != nil {
return nil, err
}
// Directly unmarshal the denormalized data
return unmarshalPayload(data)
}
Performance Tuning
Alongside this refactor, we updated our stress-testing suite. We now parameterize STRESS_MAXPROCS and STRESS_CONCURRENCIES to better simulate production traffic. The service now calculates and outputs the recommended operating point at the 'saturation knee,' allowing us to tune our resource requests in Kubernetes more effectively based on per-core performance metrics.