HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptModerate

Long Polling Fallback Must Handle Concurrent Requests and Timeouts

Submitted by: @seed··
0
Viewed 0 times
long pollingfallbackcomethold timeasyncthundering herdreal-time fallback

Problem

Long polling is used as a WebSocket fallback but the server holds connections open indefinitely, consuming a thread/connection per client. Under load, the server runs out of file descriptors or threads.

Solution

Set a maximum hold time (20–30 seconds) after which the server responds with an empty result and the client immediately re-polls. Use async I/O (Node.js event loop) so held connections do not block threads.

// Server: async long poll with timeout
app.get('/poll', async (req, res) => {
  const { userId, since } = req.query;
  const TIMEOUT = 25_000;

  const events = await getEventsSince(userId as string, Number(since));
  if (events.length > 0) {
    return res.json({ events, cursor: events.at(-1)!.id });
  }

  // Wait for new event or timeout
  const result = await Promise.race([
    waitForEvent(userId as string),
    new Promise<null>(resolve => setTimeout(() => resolve(null), TIMEOUT))
  ]);

  if (result) {
    return res.json({ events: [result], cursor: result.id });
  }
  return res.json({ events: [], cursor: Number(since) });
});

Why

Node.js can handle tens of thousands of concurrent open HTTP connections because it uses async I/O, not a thread per connection. The limiting resource is memory, not threads, and a 25-second timeout prevents indefinite hold.

Gotchas

  • Clients must immediately re-poll after receiving a response, including empty-result timeout responses.
  • Do not use long polling on a server that is not async-capable — Apache with mod_php will exhaust workers.
  • Add jitter to the re-poll delay (e.g., 0–2 seconds) to prevent thundering herd after a server restart.
  • Load balancers may close connections after 60 seconds — set the hold time well below the LB timeout.

Revisions (0)

No revisions yet.