FastPrepWebSocket Load Balancer — Parts 1–5

WebSocket Load Balancer — Parts 1–5

Stripe logoStripe● HardINTERNNEW GRADOAONSITE INTERVIEW

Problem statement

Stripe runs multiple Jupyter targets and routes long-lived WebSocket connections across them. Implement routeRequests and process the request stream in order. Targets use one-based indices from 1 through numTargets.

Request records

  • CONNECT,connectionId,userId,objectId
  • DISCONNECT,connectionId,userId,objectId
  • SHUTDOWN,targetIndex

Every successful assignment appends connectionId,userId,targetIndex to the returned log. Rejected connections and actions that do not assign a connection append nothing.

Part 1: Least-loaded routing

A new connection without an active object affinity goes to the active target with the fewest connections. Break a load tie by smaller target index.

Part 2: Disconnect

DISCONNECT removes the active connection with that ID and frees its target slot. A disconnect for a non-active ID is a no-op.

Part 3: Object affinity

While an object has active connections, every later connection for that objectId must use the same target. When the last active connection for an object disappears, its affinity is cleared.

Part 4: Capacity and duplicate IDs

No target may exceed maxConnectionsPerTarget. If the target selected by the preceding rules is full, reject the connection without trying another target. If a CONNECT repeats an active connectionId, keep state unchanged and append that connection's original user and target log.

Part 5: Shutdown and rerouting

SHUTDOWN,targetIndex temporarily excludes that target from routing. First remove all of its active connections and clear their old state, including any object affinity whose last connection was removed. Then reroute the evicted connections in ascending lexicographic connectionId order with Parts 1–4. The shutting-down target remains ineligible throughout this rerouting. Each successful reroute appends a new log; an unplaceable connection is dropped without a log. After all evictions are processed, the target becomes available again for future requests. A later shutdown of the same target is processed as a new event.

Function

routeRequests(numTargets: int, maxConnectionsPerTarget: int, requests: String[]) → String[]

Examples

Example 1

numTargets = 3maxConnectionsPerTarget = 2requests = ["CONNECT,c1,u1,docA","CONNECT,c2,u2,docB","CONNECT,c3,u3,docA","DISCONNECT,c1,u1,docA","CONNECT,c4,u4,docC","CONNECT,c5,u5,docA","CONNECT,c6,u6,docA"]return = ["c1,u1,1","c2,u2,2","c3,u3,1","c4,u4,3","c5,u5,1"]

The second docA connection follows object affinity to target 1. Disconnecting c1 frees one slot there. The final docA connection is rejected because its affinity target is full, so it produces no log.

Example 2

numTargets = 3maxConnectionsPerTarget = 2requests = ["CONNECT,a,u1,x","CONNECT,b,u2,y","CONNECT,c,u3,x","CONNECT,d,u4,z","SHUTDOWN,1","CONNECT,e,u5,x","DISCONNECT,b,u2,y","CONNECT,f,u6,y"]return = ["a,u1,1","b,u2,2","c,u3,1","d,u4,3","a,u1,2","f,u6,1"]

Shutdown removes both old connections before rerouting a then c. The first joins target 2; the second is dropped because object x is then pinned to that full target. Target 1 becomes available again when shutdown finishes. After b disconnects, the new object y connection f chooses the empty target 1.

Example 3

numTargets = 2maxConnectionsPerTarget = 10requests = ["CONNECT,conn1,userA,obj1","CONNECT,conn2,userB,obj2","SHUTDOWN,1","CONNECT,conn3,userC,obj3"]return = ["conn1,userA,1","conn2,userB,2","conn1,userA,2","conn3,userC,1"]

conn1 reroutes to target 2 while target 1 is temporarily unavailable. Target 1 reopens afterward, so conn3 selects its zero load. The source example uses an unspecified large capacity; 10 is the practice value.

Constraints

  • 1 <= numTargets <= 10^5.
  • 1 <= maxConnectionsPerTarget <= 10^9.
  • 1 <= requests.length <= 2 * 10^5.
  • Every record follows one documented schema. Identifiers are non-empty and contain no commas. Connection IDs and user IDs contain only ASCII letters, digits, underscores, or hyphens; object IDs are opaque strings.
  • A SHUTDOWN target index is within 1..numTargets. Each repeated shutdown performs the temporary eviction-and-reroute operation.
  • The number of requests plus the total number of evicted connections processed across all shutdowns is at most 2 * 10^5.
  • The returned log contains at most 2048 entries, with at most 50000 ASCII characters in total across the entries, counting their identifiers, commas and target indices.
  • Output order follows successful assignments, including duplicate-ID log repeats and sorted shutdown reroutes.

More Stripe problems

See Stripe hiring insights
Saved
public String[] routeRequests(int numTargets, int maxConnectionsPerTarget, String[] requests) {
  // Write your code here.
}
numTargets3
maxConnectionsPerTarget2
requests["CONNECT,c1,u1,docA","CONNECT,c2,u2,docB","CONNECT,c3,u3,docA","DISCONNECT,c1,u1,docA","CONNECT,c4,u4,docC","CONNECT,c5,u5,docA","CONNECT,c6,u6,docA"]
expected["c1,u1,1", "c2,u2,2", "c3,u3,1", "c4,u4,3", "c5,u5,1"]
Checking account…