Skip to main content

Overview

The http_session module provides enterprise-grade HTTP session management for tif1, implementing a thread-safe singleton pattern with aggressive connection pooling, intelligent DNS resolution with DNS-over-HTTPS (DoH) fallback, and comprehensive connection reuse tracking. This infrastructure is critical to tif1’s performance characteristics, enabling high-throughput parallel data fetching while minimizing network overhead.

Why HTTP Session Management Matters

Formula 1 telemetry data consists of thousands of individual data points spread across multiple JSON files on CDN servers. A typical session load might require:
  • 20-50 HTTP requests for lap data, session metadata, and driver information
  • 100-300 HTTP requests for telemetry data when loading all drivers
  • 500+ HTTP requests when loading full season data with telemetry
Without proper connection management, each request would incur:
  • TCP handshake overhead: 1-3 round trips (50-150ms on typical connections)
  • TLS negotiation: 2-4 round trips (100-200ms)
  • DNS resolution: 20-100ms per unique hostname
The http_session module eliminates most of this overhead through connection reuse, achieving 80-95% connection reuse rates in typical workloads. This translates to 5-10x faster data loading compared to naive HTTP implementations.

Key Features

  • Thread-safe singleton pattern: Single shared session across all threads and requests
  • Aggressive connection pooling: Dynamically sized pools based on concurrency settings
  • HTTP/2 multiplexing: Multiple requests over single connections (optional)
  • HTTP/3 support: QUIC protocol for improved performance (optional)
  • DNS-over-HTTPS fallback: Automatic DoH resolver fallback for reliability
  • Connection reuse tracking: Comprehensive metrics for monitoring and optimization
  • Keep-alive optimization: Configurable timeouts and request limits per connection
  • Automatic resource cleanup: Graceful shutdown on process exit
  • Zero-trust environment handling: Disabled trust_env for predictable behavior

Core API

get_session

def get_session() -> niquests.Session
Retrieve or create the shared HTTP session using a thread-safe singleton pattern. This function implements double-checked locking to ensure only one session instance exists across all threads while minimizing lock contention. Thread Safety: The function uses a module-level lock (_session_lock) to ensure thread-safe initialization. Once the session is created, subsequent calls return the cached instance without acquiring the lock, making this operation extremely fast in the common case. Session Lifecycle:
  1. First call creates the session with optimized settings
  2. Subsequent calls return the cached instance
  3. Session persists until process exit or explicit close_session() call
  4. Automatic cleanup registered via atexit handler
Returns:
  • niquests.Session: Shared session instance configured with:
    • Dynamic connection pooling based on concurrency settings
    • DNS-over-HTTPS fallback resolvers
    • HTTP/2 multiplexing (if enabled)
    • HTTP/3 support (if not disabled)
    • Keep-alive headers with configurable timeouts
    • Disabled trust_env for predictable behavior
Implementation Details: The session is configured with:
  • HTTPAdapter mounted on https:// with custom pool settings
  • Connection pooling: pool_connections and pool_maxsize dynamically calculated
  • Keep-alive headers: Connection: keep-alive with timeout and max request limits
  • Resolver fallback: Attempts standard DNS, then Cloudflare DoH, then Google DoH
  • Multiplexing: HTTP/2 multiplexing enabled by default for optimal throughput
Performance Characteristics:
  • First call: 10-50ms (session creation + DNS resolution)
  • Subsequent calls: <1μs (cached instance return)
  • Memory overhead: ~1-2MB for session + connection pools
  • Connection reuse: 80-95% in typical workloads
Example:
from tif1.http_session import get_session

# Get the shared session (creates on first call)
session = get_session()

# Make requests (connection pooling automatic)
response = session.get("https://cdn.jsdelivr.net/gh/TracingInsights/2024/...")
print(f"Status: {response.status_code}")

# Session is reused across all tif1 operations
# No need to close manually (automatic cleanup on exit)
Advanced Usage:
from tif1.http_session import get_session
import tif1

# Configure before first session creation
config = tif1.get_config()
config.set("pool_connections", 512)
config.set("pool_maxsize", 2048)
config.set("http_multiplexed", True)

# Now get the session (will use custom settings)
session = get_session()

# Check session configuration
adapter = session.get_adapter("https://")
print(f"Pool connections: {adapter._pool_connections}")
print(f"Pool maxsize: {adapter._pool_maxsize}")
This is an internal API. Most users don’t need to interact with the HTTP session directly. The library handles all HTTP requests automatically through Session.load() and related methods.
Configuration changes only take effect before the first get_session() call. To apply new settings, call close_session() first to reset the singleton, then call get_session() again.

close_session

def close_session() -> None
Close the shared HTTP session and cleanup resources. Called automatically on exit. Example:
from tif1.http_session import close_session

# Manually close session (rarely needed)
close_session()

Connection Statistics

get_connection_stats

def get_connection_stats() -> dict[str, Any]
Get current connection pool statistics for monitoring and debugging. Returns:
  • Dictionary with connection metrics:
    • total_requests: Total number of requests made
    • connections_reused: Number of requests that reused connections
    • connections_created: Number of connection pools created
    • reuse_rate: Percentage of requests that reused connections (0-100)
Example:
from tif1.http_session import get_connection_stats

stats = get_connection_stats()
print(f"Total requests: {stats['total_requests']}")
print(f"Reuse rate: {stats['reuse_rate']:.1f}%")

reset_connection_stats

def reset_connection_stats() -> None
Reset connection statistics. Useful for testing or benchmarking. Example:
from tif1.http_session import reset_connection_stats

reset_connection_stats()

Configuration

The HTTP session is configured via the global config object. Key settings:
Config KeyTypeDefaultDescription
http_multiplexedboolTrueEnable HTTP/2 multiplexing
http_disable_http3boolFalseDisable HTTP/3 support
pool_connectionsintDynamic (min 256)Number of connection pools (auto-sized based on concurrency)
pool_maxsizeintDynamic (min 512)Maximum connections per pool (auto-sized, typically 4x pool_connections)
keepalive_timeoutint120Keep-alive timeout in seconds
keepalive_max_requestsint1000Max requests per connection
user_agentstr"tif1/0.2.0 (https://github.com/TracingInsights/tif1)"User-Agent header
http_resolverslist[str]["standard", "doh://cloudflare", "doh://google"]DNS resolvers with DoH fallback
Example:
import tif1

config = tif1.get_config()

# Disable HTTP/2 multiplexing (enabled by default)
config.set("http_multiplexed", False)

# Override automatic pool sizing
config.set("pool_connections", 512)
config.set("pool_maxsize", 2048)

# Configure DNS resolvers
config.set("http_resolvers", ["standard", "doh://cloudflare"])

DNS-over-HTTPS (DoH) Support

The HTTP session automatically falls back to DoH resolvers if standard DNS fails. This improves reliability in restrictive network environments. Default resolver order:
  1. Standard DNS
  2. Cloudflare DoH (doh://cloudflare)
  3. Google DoH (doh://google)
Custom resolvers:
import tif1

config = tif1.get_config()

# Use only DoH
config.set("http_resolvers", ["doh://cloudflare", "doh://google"])

# Use only standard DNS
config.set("http_resolvers", ["standard"])

# Custom DoH provider
config.set("http_resolvers", ["standard", "doh://custom-provider"])

Connection Pooling

The HTTP session uses aggressive connection pooling for maximum performance:
  • Connection reuse: Keeps connections alive for multiple requests
  • Pool sizing: Dynamically sized based on concurrency settings
  • Keep-alive: Configurable timeout and max requests per connection
  • Thread-safe: Single shared session across all threads
Performance benefits:
  • Eliminates TCP handshake overhead
  • Reduces TLS negotiation time
  • Improves throughput for parallel requests
  • Lowers latency for sequential requests
Example monitoring:
import tif1
from tif1.http_session import get_connection_stats

# Load session data (2021 Belgian Grand Prix Race)
session = tif1.get_session(2021, "Belgian Grand Prix", "Race")
session.load()

# Check connection reuse
stats = get_connection_stats()
print(f"Requests: {stats['total_requests']}")
print(f"Reused: {stats['connections_reused']}")
print(f"Reuse rate: {stats['reuse_rate']:.1f}%")

Advanced Configuration

HTTP/2 Multiplexing

HTTP/2 multiplexing is enabled by default to send multiple requests over a single connection. You can disable it if needed:
import tif1

config = tif1.get_config()
config.set("http_multiplexed", False)
HTTP/2 multiplexing is enabled by default for optimal performance. Only disable if you experience issues with specific CDN configurations.

Custom pool sizing

Pool sizes are automatically calculated based on concurrency settings. Override only if you have specific requirements:
import tif1

config = tif1.get_config()

# For high concurrency (e.g., loading full season data)
config.set("pool_connections", 512)
config.set("pool_maxsize", 2048)

# For low concurrency (e.g., single session analysis)
config.set("pool_connections", 64)
config.set("pool_maxsize", 256)
The library automatically sizes connection pools based on max_workers, max_concurrent_requests, and telemetry_prefetch_max_concurrent_requests settings. Manual override is rarely needed.

Keep-Alive Tuning

Adjust keep-alive settings for different network conditions:
import tif1

config = tif1.get_config()

# Longer keep-alive for stable connections
config.set("keepalive_timeout", 300)
config.set("keepalive_max_requests", 5000)

# Shorter keep-alive for unstable connections
config.set("keepalive_timeout", 30)
config.set("keepalive_max_requests", 100)

Troubleshooting

Connection pool exhaustion

If you see connection pool warnings, increase pool size:
import tif1

config = tif1.get_config()
config.set("pool_maxsize", 1024)

DNS Resolution Failures

If standard DNS fails, DoH fallback activates automatically. To force DoH:
import tif1

config = tif1.get_config()
config.set("http_resolvers", ["doh://cloudflare", "doh://google"])

Connection reuse issues

Monitor connection reuse rate to identify issues:
from tif1.http_session import get_connection_stats

stats = get_connection_stats()
if stats['reuse_rate'] < 50:
    print("Warning: Low connection reuse rate")
    print("Consider increasing keepalive_timeout")

Best Practices

  1. Don’t create multiple sessions: Use the shared session for all requests
  2. Monitor connection stats: Track reuse rate to optimize performance
  3. Tune pool size: Match pool size to your concurrency needs
  4. Use DoH in restrictive networks: Configure DoH resolvers for reliability
  5. Enable HTTP/2 carefully: Test thoroughly before enabling multiplexing
  6. Let the library manage cleanup: Session closes automatically on exit

Summary

The http_session module provides:
  • Shared HTTP session with connection pooling
  • DNS-over-HTTPS fallback for reliability
  • Connection reuse tracking and statistics
  • Configurable pool sizing and keep-alive
  • Thread-safe singleton pattern
  • Automatic resource cleanup
This infrastructure enables high-performance data fetching with minimal latency.
Last modified on May 8, 2026