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.
Python code
24 linesimport 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
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
- Use `asyncio.sleep()` when mocking latency in an async HTTP client
- 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
More from Observability & SRE
- Adding a Correlation ID to Log Context in Python medium
- Calculate Error Rate from Log Stream in Python easy
- Check if a Timestamp Falls in a Daily Maintenance Window in Python easy
- Export Metrics with OTLP Mock in Python medium
- Generate Mock CPU and Memory Metrics in Python easy
- Generate Prometheus Text Exposition Format in Python easy
Keep learning
Related tutorials and quizzes for this topic.