Skip to main content

Overview

The tif1 configuration system provides fine-grained control over every aspect of the library’s behavior, from network settings and caching strategies to data validation and performance optimization. The configuration architecture is designed with flexibility and performance in mind, allowing you to tune the library for your specific use case—whether that’s low-latency data access, high-throughput batch processing, or development debugging. This comprehensive guide covers all configuration options, their interactions, performance implications, and best practices for different deployment scenarios. Whether you’re running interactive Jupyter notebooks, building production data pipelines, or optimizing for CI/CD environments, this guide will help you configure tif1 for optimal performance.

Configuration Philosophy

tif1 is built for performance-first operation. The default configuration values are carefully chosen to provide excellent out-of-the-box performance for most use cases, but the library exposes dozens of tuning parameters for advanced users who need to squeeze every millisecond of latency or maximize throughput for their specific workload. The configuration system follows a layered override model, where settings can be specified at multiple levels with clear precedence rules:
  1. Default values — Hardcoded defaults optimized for general use
  2. Configuration file (.tif1rc) — Persistent settings stored in your home directory
  3. Environment variables (TIF1_*) — Deployment-specific overrides
  4. Programmatic API (config.set()) — Runtime adjustments based on workload
Each layer overrides the previous one, giving you maximum flexibility to configure the library for different environments (development, staging, production) and different use cases (interactive analysis, batch processing, CI/CD pipelines).

Configuration Architecture

The configuration system is implemented as a singleton pattern, ensuring that all parts of your application share the same configuration state. This design provides several benefits:
  • Consistency: All modules and components use the same settings
  • Efficiency: No redundant configuration loading or memory overhead
  • Simplicity: Single source of truth for all configuration values
  • Thread-safe reads: Multiple threads can safely read configuration values
  • Dynamic updates: Changes propagate immediately to all components
The singleton is lazily initialized on first access, loading configuration from files and environment variables in the correct precedence order. Once initialized, the configuration remains in memory for the lifetime of the Python process.

When to Configure

You should consider customizing the configuration when:
  • Performance is critical — You need to minimize latency or maximize throughput for time-sensitive applications
  • Network conditions vary — You’re on a slow connection, behind a corporate proxy, experiencing DNS issues, or have specific network requirements
  • Resource constraints exist — You need to limit memory usage, connection pools, or concurrent requests due to system limitations
  • Data validation is needed — You’re debugging data issues, implementing quality checks, or need strict validation for compliance
  • Caching behavior matters — You want to disable caching for fresh data, change cache location for shared storage, or tune cache parameters for your access patterns
  • Backend preferences differ — You prefer polars over pandas for performance, or need specific DataFrame behavior for your workflow
  • Deployment environment differs — Production, staging, development, or CI/CD environments have different performance, reliability, and debugging requirements
  • Workload characteristics change — You’re switching between interactive analysis (low concurrency) and batch processing (high concurrency)
  • Compliance requirements exist — You need to control data storage locations, disable certain features, or meet specific regulatory requirements
  • Debugging is required — You need verbose logging, validation, or specific diagnostic information

Configuration Use Cases

Different use cases benefit from different configuration strategies: Interactive Analysis (Jupyter/IPython)
  • Lower concurrency (5-20 workers) to avoid overwhelming the system
  • Enable ultra cold start for fast initial loads
  • Moderate cache settings for iterative exploration
  • Optional validation for data quality checks
Batch Processing
  • High concurrency (50-200 workers) for maximum throughput
  • Aggressive connection pooling to handle burst traffic
  • Large cache sizes to minimize redundant fetches
  • Disable validation for maximum performance
Production Services
  • Balanced concurrency based on expected load
  • Robust retry and circuit breaker settings
  • Persistent cache with appropriate sizing
  • Comprehensive logging for monitoring
CI/CD Pipelines
  • CI mode enabled for optimized testing
  • Shorter timeouts to fail fast
  • Minimal caching to ensure fresh data
  • Validation enabled to catch data issues early
Development/Debugging
  • Cache disabled for fresh data on every run
  • Validation enabled to catch issues early
  • Verbose logging (DEBUG level)
  • Lower concurrency for easier debugging

Configuration Loading Process

When tif1 initializes, it loads configuration in the following sequence:
  1. Initialize defaults — All configuration keys start with sensible default values hardcoded in the library
  2. Load config file — If a .tif1rc file exists, its values override defaults. The library searches for config files in this order:
    • Path specified in TIF1_CONFIG_FILE environment variable (if set)
    • .tif1rc in current working directory (only if TIF1_TRUST_CWD_CONFIG=true)
    • ~/.tif1rc in user’s home directory (default location)
  3. Apply environment variables — Any TIF1_* environment variables override file settings
  4. Accept runtime changes — Programmatic config.set() calls override everything
This layered approach means you can set baseline configuration in a file, override specific settings per environment with environment variables, and make dynamic adjustments at runtime based on workload characteristics. Configuration File Search Order: The library searches for configuration files in a specific order and uses the first file found:
  1. Explicit path (TIF1_CONFIG_FILE env var) — Highest priority, useful for testing or custom deployments
  2. Current directory (./.tif1rc) — Only checked if TIF1_TRUST_CWD_CONFIG=true for security
  3. Home directory (~/.tif1rc) — Default location, most common for user-specific settings
Security Note: By default, the library does not load .tif1rc from the current working directory to prevent malicious config files in untrusted directories. Set TIF1_TRUST_CWD_CONFIG=true only if you trust the current directory. Example Configuration Loading:
Configuration Validation: The configuration system performs validation when values are read (via get()), not when they’re set. This design allows you to set any value programmatically, but invalid values are rejected when accessed, falling back to the provided default. Validation includes:
  • Type checking (int, float, bool, str, list)
  • Range validation (positive numbers, valid enums)
  • Format validation (HTTPS URLs for CDNs)
  • Path expansion (~ to home directory)
Invalid values trigger warnings in the logs and return the default value instead.

Configuration File Management

File Location and Discovery

The .tif1rc configuration file is a JSON file that stores persistent configuration settings. The library searches for this file in multiple locations with a specific precedence order. Default Location:
This is the recommended location for user-specific configuration that persists across all projects. Custom Locations: You can specify a custom configuration file location using the TIF1_CONFIG_FILE environment variable:
Current Directory: For project-specific configuration, you can place a .tif1rc file in your project directory. However, for security reasons, this file is only loaded if you explicitly enable it:
Only set TIF1_TRUST_CWD_CONFIG=true in directories you trust. Malicious .tif1rc files could modify library behavior in unexpected ways.

File Format

The configuration file must be valid JSON with a single object containing key-value pairs:
Format Requirements:
  • Must be valid JSON (not JSON5, JSONC, or other variants)
  • Root element must be an object {}
  • Keys must be strings matching configuration key names
  • Values must match expected types (string, number, boolean, array)
  • Comments are not supported (JSON doesn’t allow comments)
  • Trailing commas are not allowed
Invalid File Handling: If the configuration file is invalid (malformed JSON, wrong type, etc.), the library logs a warning and continues with default values. The library never crashes due to invalid configuration files.

Creating Configuration Files

Method 1: Programmatic Creation The recommended way to create a configuration file is using the save() method:
Method 2: Manual Creation You can also create the file manually using any text editor:
Method 3: Copy from Template Start with a template and customize:

Managing Multiple Configurations

For different environments or use cases, you can maintain multiple configuration files and switch between them using environment variables. Example: Development vs Production
Example: Per-Project Configuration

Configuration File Best Practices

  1. Version control: Commit project-specific .tif1rc files to version control
  2. Documentation: Add comments in a separate README explaining configuration choices
  3. Validation: Test configuration files before deploying to production
  4. Backup: Keep backups of working configurations before making changes
  5. Minimal: Only include settings that differ from defaults to keep files small
  6. Security: Never commit sensitive information (API keys, passwords) to config files

Environment Variables

All configuration keys can be overridden using environment variables with the TIF1_ prefix. Environment variables take precedence over configuration files but are overridden by programmatic config.set() calls.

Environment Variable Naming

Configuration keys are converted to environment variables by:
  1. Adding the TIF1_ prefix
  2. Converting to uppercase
  3. Replacing underscores with underscores (no change)
Examples:
  • libTIF1_LIB
  • enable_cacheTIF1_ENABLE_CACHE
  • max_workersTIF1_MAX_WORKERS
  • cache_dirTIF1_CACHE_DIR

Type Conversion

Environment variables are strings, so the library automatically converts them to the appropriate type: Boolean Values:
  • True: 1, true, yes, on (case-insensitive)
  • False: 0, false, no, off (case-insensitive)
Numeric Values:
  • Integers: 42, 100, 0
  • Floats: 3.14, 2.0, 0.5
String Values:
  • Used as-is
List Values:
  • Comma-separated strings

Complete Environment Variable Reference

Environment Variable Use Cases

Docker Containers:
Kubernetes:
CI/CD Pipelines:
Shell Scripts:

Configuration API Reference

get_config()

Returns the global singleton configuration instance. The Config object is a singleton, meaning there’s only one instance per Python process. All calls to get_config() return the same object, ensuring configuration consistency across your entire application. Returns:
  • Config — The global configuration singleton instance
Thread Safety: The configuration object is thread-safe for reading. However, modifying configuration values (config.set()) during concurrent operations may lead to race conditions. It’s recommended to configure the library once at startup before spawning threads or processes. Example:
Singleton Behavior:

Configuration Methods

The Config object provides three primary methods for interacting with configuration values: get() for reading, set() for modifying, and save() for persisting changes to disk.

get(key, default=None)

Retrieve the value for a specific configuration key. This method includes built-in validation for many configuration keys to ensure values are within acceptable ranges and of the correct type.
Parameters:
  • key (str) — The configuration key name (case-sensitive)
  • default (Any, optional) — Default value to return if the key doesn’t exist or validation fails. Defaults to None.
Returns:
  • Any — The configuration value, or default if the key doesn’t exist or validation fails
Validation Behavior: The get() method performs automatic validation for many configuration keys:
  • Numeric values — Must be positive integers or floats for keys like timeout, max_workers, pool_connections, etc.
  • Retry countmax_retries can be 0 or positive (0 means no retries)
  • Backoff factorretry_backoff_factor must be >= 1.0
  • Library selectionlib must be either "pandas" or "polars"
  • CDN URLscdns must be a list of HTTPS URLs
  • Path expansioncache_dir automatically expands ~ to the user’s home directory
If validation fails, the method logs a warning and returns the default value instead of the invalid value. Example:
Validation Examples:

set(key, value)

Update a configuration value in memory for the current Python session. Changes made with set() are not persisted to disk unless you explicitly call save().
Parameters:
  • key (str) — The configuration key name (case-sensitive)
  • value (Any) — The new value to set. Type should match the expected type for the key.
Returns:
  • None
Behavior:
  • Changes take effect immediately for all subsequent operations
  • Changes are session-only unless you call save()
  • No validation is performed during set() — validation happens in get()
  • You can set custom keys that aren’t part of the default configuration
When to Use:
  • Runtime optimization — Adjust settings based on workload characteristics
  • A/B testing — Compare performance with different configurations
  • Dynamic tuning — Increase concurrency for large batches, decrease for small queries
  • Temporary overrides — Disable caching for a specific operation, then re-enable
Example:
Dynamic Configuration Pattern:
Persistence Pattern:
Changes made with set() only affect the current Python session. To make changes permanent, call save() after setting your desired values.
Modifying configuration during concurrent operations (multi-threading) may lead to race conditions. Configure the library at startup before spawning threads.

save(path=None)

Persist the current in-memory configuration to a JSON file on disk. This allows you to make configuration changes permanent across Python sessions.
Parameters:
  • path (Path | None, optional) — Path where the configuration file should be saved. If None, saves to the default location (~/.tif1rc). Defaults to None.
Returns:
  • None
Behavior:
  • Writes the entire current configuration (including defaults) to the specified file
  • Creates the file if it doesn’t exist
  • Overwrites the file if it already exists
  • Uses JSON format with 2-space indentation for readability
  • Logs success or failure messages
File Format: The saved file is a JSON object with all configuration keys and their current values:
Example:
Workflow Patterns: One-time setup:
Environment-specific configs:
Backup and restore:
The save() method writes the entire configuration, not just the keys you’ve modified. This ensures the saved file is a complete, self-contained configuration.
Use environment variables (TIF1_CONFIG_FILE) to load different configuration files for different environments (dev, staging, production) without modifying code.

Configuration Keys

Core Settings

str
default:"pandas"
Default DataFrame lib ("pandas" or "polars").
bool
default:"True"
Enable or disable the multi-layer caching system (memory + SQLite).
str
default:"~/.tif1/cache"
Path where the SQLite cache database is stored.
bool
default:"False"
Enable Pydantic validation of incoming JSON data.
Validation adds overhead. Disabled by default for performance.
bool
default:"True"
Enable ultra-low latency mode for first-time loads. Skips loading full session data when only specific data is needed.

Network Settings

int
default:"30"
Network request timeout in seconds.
int
default:"3"
Number of times to retry a failed CDN request.
int
default:"20"
Maximum number of concurrent workers for parallel requests.
int
default:"20"
Maximum number of concurrent HTTP requests.

HTTP Session Settings

bool
default:"True"
Enable HTTP/2 multiplexing for multiple requests over a single connection.
bool
default:"False"
Disable HTTP/3 support.
int
default:"dynamic"
Number of connection pools to maintain. If not set, automatically calculated as max(256, max_workers, max_concurrent_requests, telemetry_prefetch_max_concurrent_requests).
Most users should rely on automatic sizing. Only set explicitly for specific performance tuning.
int
default:"dynamic"
Maximum connections per pool. If not set, automatically calculated as max(512, pool_connections * 4) to handle burst traffic.
Automatically sized to 4x pool_connections with a minimum of 512. Only override for specific use cases.
int
default:"120"
Keep-alive timeout in seconds.
int
default:"1000"
Maximum requests per keep-alive connection.
str
default:"tif1/{version}"
User-Agent header sent with all HTTP requests. Useful for identifying your application in server logs or implementing custom rate limiting.Default: tif1/{version} (e.g., tif1/0.2.0)Use Cases:
  • Identify your application in CDN logs
  • Implement custom rate limiting per application
  • Debug network issues by filtering logs
  • Comply with API usage policies
list[str]
DNS resolver configuration with DNS-over-HTTPS (DoH) fallback support. The library tries resolvers in order until one succeeds.Default: ["standard", "doh://cloudflare", "doh://google"]Resolver Types:
  • standard — System DNS resolver (fastest, but may be blocked or censored)
  • doh://cloudflare — Cloudflare DNS-over-HTTPS (1.1.1.1)
  • doh://google — Google DNS-over-HTTPS (8.8.8.8)
Benefits of DoH:
  • Bypass DNS blocking or censorship
  • Improved privacy (encrypted DNS queries)
  • Reliability when system DNS is misconfigured
  • Consistent resolution across different networks
Performance Considerations:
  • System DNS (standard) is fastest when working correctly
  • DoH adds latency due to HTTPS overhead
  • DoH is useful as fallback, not primary resolver

Telemetry Settings

int
default:"32"
Maximum concurrent requests for telemetry prefetching.

Logging Settings

float
default:"60.0"
Interval in seconds for logging connection pool statistics.

Advanced Configuration

These settings are for advanced users and performance tuning. Most users should use the defaults.
int
default:"25"
Number of cache operations before committing to SQLite.
int
default:"1024"
Maximum items in the in-memory cache layer.
int
default:"2048"
Maximum telemetry items in the in-memory cache.
float
default:"30.0"
SQLite connection timeout in seconds.
list[str]
List of CDN URLs to use for data fetching. Must be HTTPS URLs.
bool
default:"False"
Use minified CDN resources (reserved for future use).
float
default:"2.0"
Exponential backoff multiplier for retries. Must be >= 1.0.
bool
default:"True"
Add random jitter to retry delays to prevent thundering herd.
float
default:"0.0"
Maximum jitter amount in seconds. Must be > 0 to have effect.
float
default:"60.0"
Maximum delay between retries in seconds.
int
default:"5"
Number of consecutive failures before circuit breaker opens.
int
default:"60"
Seconds to wait before attempting to close circuit breaker.
int
default:"10"
Maximum HTTP/2 connections per host.
int
default:"20"
HTTP/2 connection pool size.
float
default:"0.01"
Base backoff delay when connection pool is exhausted (seconds).
float
default:"0.5"
Maximum backoff delay for pool exhaustion (seconds).
float
default:"0.01"
Jitter amount for pool exhaustion backoff (seconds).
bool
default:"False"
Enable validation of lap time data using Pydantic schemas.
bool
default:"False"
Enable validation of telemetry data using Pydantic schemas.
Enabling validation adds overhead. Only enable for debugging or data quality checks.
bool
default:"True"
Automatically prefetch lap data when accessing a driver.
bool
default:"False"
Prefetch all telemetry data on first lap telemetry request.
bool
default:"False"
Prefetch all telemetry data immediately after loading laps.
bool
default:"False"
Fill cache in background during ultra cold start mode.
bool
default:"True"
Skip retries in ultra cold start mode for faster initial load.
str
default:"WARNING"
Default logging level. Use setup_logging() to change at runtime.
bool
default:"False"
Enable offline mode (cache-only, no network requests).
bool
default:"False"
Enable CI mode (optimized for continuous integration environments).
bool
default:"False"
Use categorical types for string columns in polars DataFrames.
int
default:"0"
Number of worker processes for parallel JSON parsing. 0 disables multiprocessing.
Process-pool JSON parsing can hurt performance due to IPC overhead for telemetry-heavy workloads. Keep disabled unless you have specific use cases.

Configuration file format

The .tif1rc file is a JSON file with key-value pairs:
Location:
  • Default: ~/.tif1rc
  • Custom: Specify path with TIF1_CONFIG_PATH environment variable

Environment Variables

All configuration keys can be set via environment variables with the TIF1_ prefix:

Configuration Precedence

Configuration is loaded in this order (later overrides earlier):
  1. Default values (hardcoded in library)
  2. .tif1rc file (~/.tif1rc or TIF1_CONFIG_PATH)
  3. Environment variables (TIF1_*)
  4. Programmatic calls (config.set())
Example:

Common configuration patterns

High-Performance Setup

Low-Latency Setup

Development Setup

Production Setup


Setting Log Level

While not part of the Config object, you can set the log level using setup_logging:
Or use the fastf1-compatible function:

Configuration Patterns and Recipes

This section provides comprehensive configuration recipes for common use cases, with detailed explanations of why each setting is chosen.

Maximum Performance Configuration

For absolute maximum throughput in batch processing scenarios:
Why these settings:
  • High worker counts maximize parallel fetching
  • Large connection pools prevent pool exhaustion
  • Long keep-alive reduces connection overhead
  • Disabled validation eliminates CPU overhead
  • Aggressive prefetching reduces sequential fetches
  • Large caches reduce redundant network requests
Trade-offs:
  • High memory usage (4-8GB+)
  • May overwhelm slower systems
  • Not suitable for resource-constrained environments

Minimum Latency Configuration

For interactive analysis where first-byte latency matters most:
Why these settings:
  • Ultra cold start skips unnecessary data loading
  • DoH can be faster than misconfigured system DNS
  • Moderate concurrency balances speed and resource usage
  • Short timeout fails fast on slow connections
  • HTTP/2 multiplexing reduces connection overhead
  • Selective prefetching reduces wait time for common operations
Trade-offs:
  • May skip retries on transient failures
  • Short timeout may fail on slow networks
  • Moderate concurrency limits maximum throughput

Development and Debugging Configuration

For development environments where debugging and data quality matter more than performance:
Why these settings:
  • Disabled cache ensures fresh data on every run
  • Validation catches data quality issues early
  • Low concurrency makes logs easier to follow
  • Long timeout accommodates debugging pauses
  • Full data loading helps understand data structure
  • Verbose logging provides detailed diagnostic information
Trade-offs:
  • Much slower than production configuration
  • High CPU overhead from validation
  • Verbose logs can be overwhelming

Production Service Configuration

For production services that need reliability, performance, and observability:
Why these settings:
  • Balanced concurrency handles typical load
  • Robust retry settings handle transient failures
  • Circuit breaker prevents cascading failures
  • Reasonable timeout balances reliability and speed
  • Production logging reduces noise
  • Optimized pooling handles burst traffic
Trade-offs:
  • Not maximum performance (prioritizes reliability)
  • Higher memory usage than minimal configuration
  • May be overkill for low-traffic services

CI/CD Pipeline Configuration

For continuous integration and testing environments:
Why these settings:
  • CI mode enables CI-specific optimizations
  • Disabled cache ensures tests use fresh data
  • Validation catches data quality regressions
  • Low concurrency respects CI runner limits
  • Short timeout and few retries fail fast
  • System DNS is faster in CI environments
Trade-offs:
  • Slower than production configuration
  • May fail on transient network issues
  • Not suitable for performance testing

Resource-Constrained Configuration

For systems with limited CPU, memory, or network bandwidth:
Why these settings:
  • Pandas has lower memory overhead than polars
  • Minimal concurrency reduces CPU and memory usage
  • Small pools reduce memory footprint
  • Small caches limit memory usage
  • Disabled prefetching reduces unnecessary fetches
  • Ultra cold start loads only needed data
Trade-offs:
  • Much slower than high-performance configuration
  • Sequential operations dominate execution time
  • Not suitable for large-scale analysis

Offline/Cache-Only Configuration

For working with previously cached data without network access:
Why these settings:
  • Offline mode prevents network requests
  • Cache must be enabled to serve data
  • No retries since network is unavailable
  • Short timeout fails fast on cache misses
Trade-offs:
  • Only works with previously cached data
  • Cache misses result in immediate failures
  • No way to fetch new data

High-Reliability Configuration

For scenarios where reliability matters more than performance:
Why these settings:
  • Conservative concurrency reduces load on CDN
  • Aggressive retries handle transient failures
  • Long timeout accommodates slow networks
  • Conservative circuit breaker tolerates more failures
  • Multiple DNS resolvers provide fallback
  • Cache provides redundancy
Trade-offs:
  • Slower than performance-optimized configuration
  • May retry excessively on persistent failures
  • Higher latency due to conservative settings

Memory-Optimized Configuration

For minimizing memory usage while maintaining reasonable performance:
Why these settings:
  • Pandas has lower memory overhead
  • Moderate concurrency balances speed and memory
  • Small caches reduce memory footprint
  • Frequent commits reduce memory buffer size
  • Smaller pools reduce connection overhead
  • Disabled prefetching reduces memory usage
Trade-offs:
  • Slower than high-performance configuration
  • More frequent disk I/O from cache commits
  • May not be suitable for large-scale analysis

Configuration Troubleshooting

Common Configuration Issues

Issue: Configuration changes not taking effect Symptoms:
  • Changes made with config.set() don’t seem to work
  • Environment variables are ignored
  • Config file changes don’t apply
Solutions:
  1. Check configuration precedence (programmatic > env > file > defaults)
  2. Verify environment variable names (must be TIF1_ prefix, uppercase)
  3. Ensure config file is valid JSON
  4. Check config file location (use TIF1_CONFIG_FILE to specify)
  5. Restart Python process after changing config file
  6. Check for validation failures in logs

Issue: Poor performance despite high concurrency settings Symptoms:
  • High max_workers but slow execution
  • Connection pool exhaustion warnings
  • Low CPU utilization
Solutions:
  1. Check if connection pool is too small
  2. Verify network bandwidth isn’t saturated
  3. Check if CDN is rate limiting
  4. Ensure cache is enabled
  5. Monitor connection reuse rate

Issue: High memory usage Symptoms:
  • Python process using excessive memory
  • Out of memory errors
  • System slowdown
Solutions:
  1. Reduce cache sizes
  2. Lower concurrency
  3. Use pandas instead of polars
  4. Disable prefetching
  5. Enable ultra cold start

Issue: Frequent timeout errors Symptoms:
  • Many timeout errors in logs
  • Slow data loading
  • Inconsistent performance
Solutions:
  1. Increase timeout value
  2. Check network connectivity
  3. Try different DNS resolvers
  4. Reduce concurrency
  5. Enable retries

Issue: Cache not working Symptoms:
  • Every request hits the network
  • No performance improvement on repeated queries
  • Cache directory empty
Solutions:
  1. Verify cache is enabled
  2. Check cache directory permissions
  3. Ensure cache directory exists
  4. Check disk space
  5. Verify SQLite timeout isn’t too short

Best Practices

Configuration Strategy

  1. Start with defaults — The default configuration is optimized for most use cases. Only change settings when you have a specific need.
  2. Use config files for persistent settings — Store common settings in ~/.tif1rc for user-specific configuration that persists across all projects.
  3. Use environment variables for deployment — Configure per-environment settings (dev, staging, production) using environment variables without modifying code.
  4. Use programmatic API for runtime changes — Adjust settings dynamically based on workload characteristics or user preferences.
  5. Document your configuration — Keep a README or comments explaining why specific settings were chosen.
  6. Test configuration changes — Verify performance impact before deploying to production. Use benchmarks to measure improvements.
  7. Monitor in production — Track connection stats, cache hit rates, and error rates to validate configuration choices.
  8. Version control project configs — Commit project-specific .tif1rc files to version control for reproducibility.

Performance Optimization

  1. Let pool sizing auto-calculate — Only override pool_connections and pool_maxsize for specific tuning needs. The automatic sizing works well for most cases.
  2. Monitor connection reuse — Enable connection stats logging to track connection reuse rate. Low reuse indicates pool exhaustion.
  3. Balance concurrency and resources — Higher concurrency isn’t always better. Find the sweet spot for your system and network.
  4. Use polars for large datasets — Polars provides better performance for large-scale analysis, but pandas has lower memory overhead.
  5. Enable caching — Cache dramatically improves performance for repeated queries. Only disable for debugging or when fresh data is critical.
  6. Tune prefetching — Enable prefetching for common access patterns, but disable for memory-constrained environments.
  7. Use ultra cold start — Enable for interactive analysis where first-byte latency matters. Disable for batch processing that needs all data.

Reliability and Robustness

  1. Keep validation disabled in production — Enable only for debugging or data quality checks. Validation adds significant overhead.
  2. Configure robust retry settings — Use exponential backoff with jitter to handle transient failures gracefully.
  3. Set appropriate timeouts — Balance between failing fast and tolerating slow networks. 30-60 seconds is reasonable for most cases.
  4. Use circuit breakers — Configure circuit breaker thresholds to prevent cascading failures.
  5. Multiple DNS resolvers — Use DoH as fallback for reliability, but prefer system DNS for performance.
  6. Monitor error rates — Track timeout, retry, and circuit breaker events to identify configuration issues.

Security and Privacy

  1. Trust config files carefully — Only set TIF1_TRUST_CWD_CONFIG=true in directories you trust.
  2. Use DoH for privacy — DNS-over-HTTPS encrypts DNS queries, improving privacy on untrusted networks.
  3. Validate config files — Ensure config files are valid JSON and don’t contain malicious values.
  4. Limit cache locations — Store cache in secure locations with appropriate permissions.
  5. Custom user agents — Use descriptive user agents to identify your application in logs.

Development Workflow

  1. Separate dev and prod configs — Maintain different configurations for development and production environments.
  2. Use CI mode in pipelines — Enable ci_mode for CI/CD-specific optimizations.
  3. Enable validation in dev — Catch data quality issues early by enabling validation in development.
  4. Disable cache in dev — Ensure fresh data during development by disabling cache.
  5. Verbose logging in dev — Use DEBUG logging to understand library behavior during development.

Memory Management

  1. Monitor memory usage — Track Python process memory to identify configuration issues.
  2. Reduce cache sizes — Lower cache sizes if memory usage is too high.
  3. Use pandas for low memory — Pandas has lower memory overhead than polars.
  4. Disable prefetching — Reduce memory usage by disabling aggressive prefetching.
  5. Frequent cache commits — Reduce memory buffer size by committing cache more frequently.

Troubleshooting

  1. Enable debug logging — Use tif1.setup_logging(logging.DEBUG) to see detailed diagnostic information.
  2. Check configuration values — Verify actual configuration values with config.get().
  3. Monitor connection stats — Enable connection stats logging to track pool usage.
  4. Test incrementally — Change one setting at a time to isolate issues.
  5. Compare with defaults — Reset to defaults to verify custom configuration is the issue.

Configuration Maintenance

  1. Review periodically — Revisit configuration as workload characteristics change.
  2. Update with library — Check release notes for new configuration options.
  3. Benchmark regularly — Measure performance to validate configuration choices.
  4. Document changes — Keep a changelog of configuration changes and their rationale.
  5. Backup working configs — Save backups before making experimental changes.

Summary

The tif1 configuration system provides comprehensive control over library behavior through multiple configuration sources with clear precedence rules. Key takeaways:

Configuration Sources (Precedence Order)

  1. Programmatic API (config.set()) — Highest precedence, runtime changes
  2. Environment variables (TIF1_*) — Deployment-specific overrides
  3. Configuration file (.tif1rc) — Persistent user settings
  4. Default values — Hardcoded defaults optimized for general use

Key Features

  • Singleton pattern — Single configuration instance per Python process
  • Lazy initialization — Configuration loaded on first access
  • Validation on read — Invalid values rejected when accessed, not when set
  • Type conversion — Automatic conversion from environment variables
  • Path expansion — Automatic ~ expansion for paths
  • Thread-safe reads — Safe to read from multiple threads

Configuration Categories

  • Core settings — DataFrame library, caching, validation
  • Network settings — Timeouts, retries, concurrency
  • HTTP session — Connection pooling, keep-alive, multiplexing
  • Cache configuration — Memory limits, commit intervals, SQLite settings
  • CDN configuration — CDN URLs, minification
  • Retry & circuit breaker — Backoff, jitter, thresholds
  • Prefetch strategies — Automatic data prefetching
  • Telemetry settings — Telemetry-specific concurrency
  • Logging — Log levels, connection stats
  • Advanced settings — Polars options, JSON parsing, offline mode

Common Use Cases

  • Maximum performance — High concurrency, large pools, aggressive prefetching
  • Minimum latency — Ultra cold start, DoH, moderate concurrency
  • Development — Disabled cache, enabled validation, verbose logging
  • Production — Balanced settings, robust retries, monitoring
  • CI/CD — CI mode, disabled cache, fast failure
  • Resource-constrained — Low concurrency, small caches, minimal prefetching
  • Offline — Cache-only mode, no network requests
  • High-reliability — Aggressive retries, long timeouts, multiple resolvers

Best Practices Summary

  1. Start with defaults, change only when needed
  2. Use config files for persistent settings
  3. Use environment variables for deployment
  4. Use programmatic API for runtime changes
  5. Monitor performance and adjust accordingly
  6. Document configuration choices
  7. Test changes before production deployment
  8. Keep validation disabled in production
  9. Enable caching for performance
  10. Balance concurrency with resources

Getting Help

If you encounter configuration issues:
  1. Enable debug logging: tif1.setup_logging(logging.DEBUG)
  2. Check actual values: config.get(key)
  3. Verify precedence: Check file, env vars, and programmatic sets
  4. Review validation: Check logs for validation warnings
  5. Compare with defaults: Reset to defaults to isolate issues
  6. Consult documentation: Review this guide for detailed explanations
The configuration system is designed to be flexible, powerful, and easy to use. Whether you’re running interactive notebooks, building production pipelines, or optimizing for specific workloads, the configuration system provides the tools you need to tune tif1 for your use case.

Configuration Reference Tables

Quick Reference: Common Settings

Quick Reference: Performance Impact

Legend: ↑ = Increases, ↓ = Decreases

Quick Reference: Memory Usage

Memory estimates are approximate and depend on workload

Quick Reference: Concurrency Settings


Caching Strategy

Learn about the multi-layer caching system and how to optimize cache configuration

Best Practices

Advanced performance optimization techniques and benchmarking

HTTP Session

Deep dive into HTTP session configuration and connection pooling

Installation

Setup guide and initial configuration

CLI Configuration

Configure tif1 via command-line interface

Backends

Pandas vs Polars backend comparison and configuration

Additional Resources

Example Configuration Files

Minimal Configuration:
Typical Configuration:
Complete Configuration (All Defaults):

Configuration Validation Script

Use this script to validate your configuration:

Configuration Migration Script

Use this script to migrate from old configuration format:

Environment Variable Generator

Use this script to generate environment variables from config file:

Frequently Asked Questions

Q: Do I need to configure tif1? A: No, the default configuration works well for most use cases. Only configure if you have specific performance, reliability, or resource requirements. Q: What’s the difference between config file and environment variables? A: Config files are persistent and user-specific. Environment variables are deployment-specific and override config files. Use config files for personal settings, environment variables for deployment settings. Q: Can I use multiple config files? A: Yes, use the TIF1_CONFIG_FILE environment variable to specify which config file to load. Only one config file is loaded at a time (first found in search order). Q: How do I reset to default configuration? A: Delete or rename your .tif1rc file and unset all TIF1_* environment variables. The library will use hardcoded defaults. Q: Why isn’t my configuration taking effect? A: Check configuration precedence (programmatic > env > file > defaults). Verify environment variable names are correct (TIF1_ prefix, uppercase). Ensure config file is valid JSON. Check logs for validation warnings. Q: What’s the performance impact of validation? A: Validation adds 10-30% overhead depending on workload. Disable in production for maximum performance. Q: Should I use pandas or polars? A: Polars is faster for large datasets but uses more memory. Pandas has lower memory overhead and better compatibility. Start with pandas, switch to polars if you need more performance. Q: How much memory does tif1 use? A: Depends on configuration and workload. Typical usage: 200-500 MB. High-performance: 1-2 GB. Maximum: 4-8 GB+. Reduce cache sizes and concurrency to lower memory usage. Q: What’s ultra cold start mode? A: Ultra cold start skips loading full session data when only specific data is needed, reducing initial load time by 50-80%. Enable for interactive analysis, disable for batch processing. Q: How do I optimize for my use case? A: See the “Configuration Patterns and Recipes” section for detailed configurations for different use cases (performance, latency, development, production, etc.). Q: Can I change configuration at runtime? A: Yes, use config.set() to change values at runtime. Changes take effect immediately but are not persisted unless you call config.save(). Q: What’s the recommended production configuration? A: See the “Production Service Configuration” in the “Configuration Patterns and Recipes” section for a complete production-ready configuration. Q: How do I debug configuration issues? A: Enable debug logging (tif1.setup_logging(logging.DEBUG)), check actual values (config.get(key)), verify precedence, and review logs for validation warnings. Q: What’s the difference between pool_connections and pool_maxsize? A: pool_connections is the number of connection pools (one per host). pool_maxsize is the maximum connections per pool. Both auto-calculate by default based on concurrency settings. Q: Should I enable prefetching? A: Enable for common access patterns (e.g., accessing driver laps after loading session). Disable for memory-constrained environments or when access patterns are unpredictable. Q: What’s the recommended cache size? A: Default (1024 items) works for most cases. Increase for large-scale analysis (4096+). Decrease for memory-constrained environments (256-512). Q: How do I configure for CI/CD? A: Enable ci_mode, disable cache, enable validation, use lower concurrency, shorter timeout, and fewer retries. See “CI/CD Pipeline Configuration” for details. Q: Can I use tif1 offline? A: Yes, enable offline_mode to use only cached data. Requires previously cached data. See “Offline/Cache-Only Configuration” for details. Q: What’s the impact of HTTP/2 multiplexing? A: HTTP/2 multiplexing reduces connection overhead by reusing connections for multiple requests. Enabled by default. Disable only if you have issues with specific proxies or CDNs. Q: How do I configure DNS resolvers? A: Use http_resolvers to specify resolver order. Default tries system DNS first, then DoH fallbacks. Use DoH for privacy or when system DNS is blocked. Q: What’s the circuit breaker for? A: Circuit breaker prevents cascading failures by stopping requests after consecutive failures. Automatically recovers after timeout. Configure threshold and timeout based on reliability requirements. Q: How do I monitor configuration effectiveness? A: Enable connection stats logging, track cache hit rates, monitor error rates, and benchmark performance. Adjust configuration based on metrics.
Last modified on May 8, 2026