How to Mock HTTP Client Latency in Python

Simulate outbound HTTP request latency with configurable ranges to test timeouts, retries, and SLO monitoring without external services.

Easy Python 3.10+ Aug 9, 2026 Observability & SRE 14 views 0 copies

Python code

24 lines
Python 3.10+
import time
import random

def mock_latency(host: str, min_ms: int = 100, max_ms: int = 500) -> dict:
    """Simulate an outbound HTTP request with mock latency."""
    latency_ms = random.randint(min_ms, max_ms)
    start = time.perf_counter()
    time.sleep(latency_ms / 1000)
    elapsed_ms = (time.perf_counter() - start) * 1000
    
    return {
        "host": host,
        "method": "GET",
        "status": 200,
        "measured_latency_ms": round(elapsed_ms, 2),
        "mock_latency_ms": latency_ms,
    }

if __name__ == "__main__":
    random.seed(42)
    for host in ["https://api.example.com", "https://test-service.io"]:
        result = mock_latency(host)
        print(f"{result['host']}: measured={result['measured_latency_ms']}ms "
              f"(mock range: {result['mock_latency_ms']}ms)")

Output

stdout
https://api.example.com: measured=403.21ms (mock range: 403ms)
https://test-service.io: measured=477.87ms (mock range: 478ms)

How it works

The time.perf_counter() call measures wall-clock time with high resolution, and time.sleep() blocks exactly the random mocked latency. This approach gives deterministic, reproducible testing of outbound call behavior. Scaling to milliseconds converts the sleep duration for Python's seconds-based sleep. Using random.seed() makes the mock reproducible across runs for debugging and CI. The returned dict mirrors a real HTTP response object, so downstream code can consume it without changes.

Common mistakes

  • Using `time.monotonic()` instead of `time.perf_counter()` — the former is system-uptime based and less precise
  • Forgetting to scale milliseconds to seconds in `time.sleep()` — sleeping microseconds instead of milliseconds
  • Not seeding `random` for reproducible test results across runs
  • Measuring latency with `time.time()` which can jump backward with NTP corrections

Variations

  1. Use `asyncio.sleep()` when mocking latency in an async HTTP client
  2. Return a fake `requests.Response`-like object with headers and body for full client compatibility

Real-world use cases

  • Testing retry and circuit-breaker logic in service-to-service calls by injecting variable latency before unit tests
  • Validating SLO and alert thresholds in observability dashboards with repeatable latency patterns
  • Stress-testing timeout settings in HTTP client pools without relying on flaky external networks

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Observability & SRE

Related tutorials and quizzes for this topic.