Topic Overview

Keep-alive vs Long Polling

Compare HTTP keep-alive and long polling techniques for maintaining connections and real-time communication.


HTTP Keep-alive

Keep-alive reuses the same TCP connection for multiple HTTP requests.

Without Keep-alive

Request 1: TCP connection → Request → Response → Close
Request 2: TCP connection → Request → Response → Close
Request 3: TCP connection → Request → Response → Close

Overhead: 3-way handshake for each request

With Keep-alive

TCP connection (established once)
  Request 1 → Response 1
  Request 2 → Response 2
  Request 3 → Response 3
Connection stays open

Benefits: Reuse connection, reduce overhead


Long Polling

Long polling holds HTTP request open until server has data to send.

How Long Polling Works

1. Client sends request
2. Server holds request (doesn't respond immediately)
3. When data available: Server responds
4. Client immediately sends new request
5. Repeat

Use case: Real-time updates when WebSockets not available


Comparison

FeatureKeep-aliveLong Polling
PurposeReuse connectionReal-time updates
ConnectionStays openHeld open until data
OverheadReduced (reuse)Higher (held connections)
Use caseMultiple requestsReal-time notifications
LatencyRequest-responseLower (server push)

Examples

HTTP Keep-alive

import requests

# Session with keep-alive
session = requests.Session()

# Multiple requests reuse connection
response1 = session.get('https://api.example.com/data1')
response2 = session.get('https://api.example.com/data2')
response3 = session.get('https://api.example.com/data3')

# Connection reused (no new handshake)

Long Polling

import requests
import time

def long_poll(url, timeout=30):
    """Long polling request"""
    while True:
        try:
            # Server holds request until data available
            response = requests.get(url, timeout=timeout)
            
            if response.status_code == 200:
                data = response.json()
                process_data(data)
            
            # Immediately send new request
            time.sleep(0.1)
        except requests.Timeout:
            # Timeout: Send new request
            continue

Long Polling Server

from flask import Flask, jsonify
import time

app = Flask(__name__)

@app.route('/poll')
def poll():
    """Long polling endpoint"""
    # Wait for data (max 30 seconds)
    start_time = time.time()
    timeout = 30
    
    while time.time() - start_time < timeout:
        # Check if data available
        data = check_for_updates()
        if data:
            return jsonify(data)
        
        time.sleep(0.5)  # Check every 0.5 seconds
    
    # Timeout: Return empty response
    return jsonify({'status': 'timeout'}), 200

Common Pitfalls

  • Keep-alive timeout: Connection closed prematurely. Fix: Configure appropriate timeout
  • Long polling connections: Too many held connections. Fix: Limit connections, use timeouts
  • Not using keep-alive: Wasting resources. Fix: Enable keep-alive for multiple requests
  • Long polling overhead: High server load. Fix: Use WebSockets for better performance

Interview Questions

Beginner

Q: What is HTTP keep-alive and how does it differ from long polling?

A:

HTTP Keep-alive:

Reuses TCP connection for multiple requests:

TCP connection (established once)
  Request 1 → Response 1
  Request 2 → Response 2
  Request 3 → Response 3
Connection stays open

Benefits:

  • Reduced overhead: No new handshake per request
  • Faster: Reuse existing connection
  • Efficient: Multiple requests on one connection

Long Polling:

Holds HTTP request open until data available:

1. Client sends request
2. Server holds request (doesn't respond)
3. When data available: Server responds
4. Client immediately sends new request

Use case: Real-time updates (when WebSockets not available)

Differences:

FeatureKeep-aliveLong Polling
PurposeReuse connectionReal-time updates
ConnectionOpen for requestsHeld until data
OverheadReducedHigher

Intermediate

Q: Explain how long polling works and when you would use it vs WebSockets.

A:

Long Polling Process:

  1. Client sends request

    GET /updates
    
  2. Server holds request

    Server doesn't respond immediately
    Waits for data (up to timeout)
    
  3. Data available

    Server responds with data
    
  4. Client immediately requests again

    GET /updates (new request)
    

Example:

# Client
while True:
    response = requests.get('/updates', timeout=30)
    if response.status_code == 200:
        process(response.data)
    # Immediately send new request

Long Polling vs WebSockets:

FeatureLong PollingWebSockets
ProtocolHTTPWebSocket
ConnectionHTTP request heldPersistent connection
OverheadHigher (new request each time)Lower (one connection)
LatencyHigherLower
ComplexitySimplerMore complex
Browser supportUniversalModern browsers

When to use:

  • Long polling: Simple, works everywhere, WebSockets not available
  • WebSockets: Real-time, low latency, bidirectional

Senior

Q: Design a system that uses both keep-alive and long polling efficiently. How do you manage connections, handle timeouts, and optimize for performance?

A:

class HybridConnectionSystem {
  private keepAliveManager: KeepAliveManager;
  private longPollManager: LongPollManager;
  
  constructor() {
    this.keepAliveManager = new KeepAliveManager();
    this.longPollManager = new LongPollManager();
  }
  
  // 1. Keep-alive for Regular Requests
  class KeepAliveManager {
    private connections: Map<string, Connection>;
    
    async getConnection(host: string): Promise<Connection> {
      // Reuse existing connection
      if (this.connections.has(host)) {
        const conn = this.connections.get(host);
        if (conn.isAlive()) {
          return conn;
        }
      }
      
      // Create new connection
      const conn = await this.createConnection(host);
      this.connections.set(host, conn);
      return conn;
    }
    
    async request(url: string, options: RequestOptions): Promise<Response> {
      const host = this.extractHost(url);
      const conn = await this.getConnection(host);
      return await conn.request(url, options);
    }
  }
  
  // 2. Long Polling for Real-time
  class LongPollManager {
    private polls: Map<string, Poll>;
    
    async poll(endpoint: string, callback: Function): Promise<void> {
      while (true) {
        try {
          const response = await this.longPollRequest(endpoint, {
            timeout: 30
          });
          
          if (response.data) {
            callback(response.data);
          }
          
          // Immediately poll again
        } catch (error) {
          if (error instanceof TimeoutError) {
            // Timeout: Poll again
            continue;
          } else {
            // Error: Retry with backoff
            await this.retryWithBackoff(endpoint, callback);
          }
        }
      }
    }
    
    async longPollRequest(endpoint: string, options: RequestOptions): Promise<Response> {
      // Server holds request until data available
      return await fetch(endpoint, {
        ...options,
        headers: {
          'Connection': 'keep-alive'
        }
      });
    }
  }
  
  // 3. Connection Management
  optimizeConnections(): void {
    // Keep-alive: Reuse connections
    // Long polling: Limit concurrent polls
    // Timeout management: Close idle connections
  }
}

Features:

  1. Keep-alive: Reuse connections for regular requests
  2. Long polling: Real-time updates
  3. Connection management: Optimize, limit, timeout

Key Takeaways

  • Keep-alive: Reuse TCP connection for multiple HTTP requests
  • Long polling: Hold HTTP request open until data available
  • Keep-alive benefits: Reduced overhead, faster, efficient
  • Long polling use: Real-time updates when WebSockets not available
  • Comparison: Keep-alive for efficiency, long polling for real-time
  • Best practices: Use keep-alive for multiple requests, long polling for real-time, consider WebSockets

About the author

InterviewCrafted helps you master system design with patience. We believe in curiosity-led engineering, reflective writing, and designing systems that make future changes feel calm.