Best Practices
Production Optimization Guide
Advanced patterns, performance optimization, and reliability best practices for Predax integration.
Caching Strategy
Caching IP checks reduces API calls, improves response time, and saves on quota usage.
Recommended Cache TTL:
- • IP Risk Scores: 24 hours (risk profiles change slowly)
- • Geolocation: 7 days (rarely changes)
- • ASN/Network: 30 days (very stable)
- • High-Risk IPs: 6 hours (more dynamic)
Example: Redis Caching (Python)
import redis
import json
from datetime import timedelta
redis_client = redis.Redis(host='localhost', port=6379, db=0)
def check_ip_with_cache(ip_address):
cache_key = f"ip_check:{ip_address}"
# Try cache first
cached = redis_client.get(cache_key)
if cached:
return json.loads(cached)
# Cache miss - call API
result = requests.post(
'https://predax.io/api/v1/check/ip',
headers={'X-API-Key': API_KEY},
json={'ip': ip_address},
timeout=2.0
).json()
# Cache for 24 hours
redis_client.setex(
cache_key,
timedelta(hours=24),
json.dumps(result)
)
return resultExample: In-Memory Cache (Node.js)
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 86400 }); // 24 hours
async function checkIpWithCache(ipAddress) {
const cacheKey = `ip_check:${ipAddress}`;
// Try cache first
const cached = cache.get(cacheKey);
if (cached) {
return cached;
}
// Cache miss - call API
const response = await fetch('https://predax.io/api/v1/check/ip', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({ ip: ipAddress }),
signal: AbortSignal.timeout(2000)
});
const result = await response.json();
// Cache result
cache.set(cacheKey, result);
return result;
}Robust Error Handling
Handle API errors gracefully to ensure your application remains reliable even when issues occur.
Fail-Safe Principle:
When the API is unavailable or quota is exceeded, fail open (allow the request) rather than blocking all users. False negatives are better than false positives.
Example: Complete Error Handling (Python)
import requests
import logging
from requests.exceptions import Timeout, RequestException
logger = logging.getLogger(__name__)
def check_ip_safe(ip_address, user_id=None):
"""
Check IP with comprehensive error handling.
Returns (result_dict, is_cached_or_default)
"""
try:
response = requests.post(
'https://predax.io/api/v1/check/ip',
headers={
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
json={'ip': ip_address, 'user_id': user_id},
timeout=2.0
)
# Log request ID for debugging
request_id = response.headers.get('X-Request-ID')
logger.info(f"IP check for {ip_address}, request_id={request_id}")
if response.status_code == 200:
return response.json(), False
elif response.status_code == 429:
# Rate limited - wait and retry once
logger.warning(f"Rate limited for {ip_address}, retrying...")
time.sleep(1)
return check_ip_safe(ip_address, user_id)
elif response.status_code == 402:
# Quota exceeded - fail open
logger.error(f"Quota exceeded, failing open for {ip_address}")
return get_default_result(ip_address), True
elif response.status_code == 401:
# Invalid API key - critical error
logger.critical("Invalid API key!")
return get_default_result(ip_address), True
else:
# Other error - fail open
logger.error(f"API error {response.status_code} for {ip_address}")
return get_default_result(ip_address), True
except Timeout:
logger.warning(f"Timeout checking {ip_address}, failing open")
return get_default_result(ip_address), True
except RequestException as e:
logger.error(f"Request exception for {ip_address}: {e}")
return get_default_result(ip_address), True
def get_default_result(ip_address):
"""Return safe default when API unavailable"""
return {
'ip': ip_address,
'classification': {
'risk_score': 0,
'risk_level': 'unknown',
'is_proxy': False,
'is_vpn': False,
'is_tor': False,
'is_datacenter': False
},
'meta': {
'request_id': 'fallback',
'note': 'API unavailable - using defaults'
}
}Retry Logic with Exponential Backoff
Implement smart retries for transient failures (429, 5xx) without overwhelming the API.
Example: Exponential Backoff (Python)
import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
def create_session_with_retries():
"""Create session with automatic retry logic"""
session = requests.Session()
# Retry on 429 (rate limit) and 5xx (server errors)
retry_strategy = Retry(
total=3,
status_forcelist=[429, 500, 502, 503, 504],
backoff_factor=1, # 1s, 2s, 4s
allowed_methods=["POST"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("https://", adapter)
session.mount("http://", adapter)
return session
# Usage
session = create_session_with_retries()
response = session.post(
'https://predax.io/api/v1/check/ip',
headers={'X-API-Key': API_KEY},
json={'ip': '8.8.8.8'},
timeout=2.0
)Example: Manual Retry (Node.js)
async function checkIpWithRetry(ipAddress, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch('https://predax.io/api/v1/check/ip', {
method: 'POST',
headers: {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({ ip: ipAddress }),
signal: AbortSignal.timeout(2000)
});
if (response.ok) {
return await response.json();
}
// Retry on rate limit or server errors
if (response.status === 429 || response.status >= 500) {
if (attempt < maxRetries) {
const backoffMs = Math.pow(2, attempt - 1) * 1000; // 1s, 2s, 4s
console.log(`Retry ${attempt}/${maxRetries} after ${backoffMs}ms`);
await new Promise(resolve => setTimeout(resolve, backoffMs));
continue;
}
}
throw new Error(`API error: ${response.status}`);
} catch (error) {
if (attempt === maxRetries) {
throw error;
}
}
}
}Client-Side Rate Limiting
Prevent hitting rate limits by implementing client-side throttling.
Example: Token Bucket (Python)
import time
import threading
class RateLimiter:
def __init__(self, max_requests_per_second):
self.max_requests = max_requests_per_second
self.tokens = max_requests_per_second
self.last_update = time.time()
self.lock = threading.Lock()
def acquire(self):
"""Wait until a token is available"""
with self.lock:
now = time.time()
elapsed = now - self.last_update
# Replenish tokens
self.tokens = min(
self.max_requests,
self.tokens + elapsed * self.max_requests
)
self.last_update = now
if self.tokens >= 1:
self.tokens -= 1
return True
# Wait for next token
wait_time = (1 - self.tokens) / self.max_requests
time.sleep(wait_time)
self.tokens = 0
return True
# Usage
rate_limiter = RateLimiter(max_requests_per_second=10)
def check_ip_rate_limited(ip_address):
rate_limiter.acquire()
return check_ip_safe(ip_address)Batch Processing Optimization
Use the bulk endpoint to check multiple IPs efficiently (max 100 per request).
When to Use Bulk:
- • Processing historical data
- • Batch fraud review
- • Log analysis
- • Warming up caches
Example: Batch Processing (Python)
def check_ips_in_batches(ip_list, batch_size=100):
"""
Check multiple IPs using bulk endpoint.
Automatically chunks into batches of 100.
"""
results = []
for i in range(0, len(ip_list), batch_size):
batch = ip_list[i:i + batch_size]
try:
response = requests.post(
'https://predax.io/api/v1/check/ip/bulk',
headers={
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
},
json={'ips': batch},
timeout=5.0
)
if response.status_code == 200:
batch_results = response.json()
results.extend(batch_results)
else:
logger.error(f"Bulk check failed: {response.status_code}")
except Exception as e:
logger.error(f"Bulk check exception: {e}")
# Rate limiting between batches
time.sleep(0.1)
return results
# Usage
all_ips = ["1.1.1.1", "8.8.8.8", ...] # Your IP list
results = check_ips_in_batches(all_ips)Monitoring & Alerting
Track API health, quota usage, and error rates in production.
Key Metrics to Monitor:
API Response Time
Track p50, p95, p99 latencies. Alert if p95 > 2s
Error Rate
Track 4xx and 5xx errors. Alert if > 1%
Quota Usage
Alert when 80% of daily or monthly quota used
Cache Hit Rate
Track cache effectiveness. Aim for > 60%
Example: Prometheus Metrics (Python)
from prometheus_client import Counter, Histogram
# Define metrics
api_requests_total = Counter(
'predax_api_requests_total',
'Total Predax API requests',
['status_code']
)
api_request_duration = Histogram(
'predax_api_request_duration_seconds',
'Predax API request duration'
)
quota_remaining = Gauge(
'predax_quota_remaining',
'Remaining quota',
['period'] # 'daily' or 'monthly'
)
# Track in API calls
@api_request_duration.time()
def check_ip_monitored(ip_address):
try:
response = requests.post(...)
# Record metrics
api_requests_total.labels(
status_code=response.status_code
).inc()
# Track quota
remaining_today = int(
response.headers.get('X-Quota-Remaining-Today', 0)
)
quota_remaining.labels(period='daily').set(remaining_today)
return response.json()
except Exception as e:
api_requests_total.labels(status_code='error').inc()
raiseSecurity Best Practices
Protect your API keys and implement secure integration patterns.
🔒 Never Expose API Keys
Never commit API keys to version control or expose them in client-side code. Use environment variables or secrets managers.
🔒 Use Backend Proxies
Always call Predax from your backend, never directly from browsers or mobile apps. This prevents key exposure and rate limit abuse.
🔒 Rotate Keys Periodically
Generate new API keys every 90 days and update your application. Keep old keys active briefly for zero-downtime rotation.
🔒 Use HTTPS Only
Always use https:// endpoints. Never use http:// in production.
Performance Optimization Tips
⚡ Run Checks Asynchronously
Don't block user requests waiting for IP checks. Use background jobs or async workers.
⚡ Check Only When Necessary
Only check IPs on sensitive actions (login, signup, checkout). Don't check every page view.
⚡ Use Connection Pooling
Reuse HTTP connections with session objects. Don't create new connections for each request.
⚡ Pre-warm Caches
For high-traffic applications, pre-populate your cache with known IPs using bulk checks.
Quick Reference Checklist
Before Production:
- ✓ Implement caching (24h TTL)
- ✓ Add timeout (2-3s)
- ✓ Add retry logic with backoff
- ✓ Implement fail-open error handling
- ✓ Log X-Request-ID headers
Monitoring Setup:
- ✓ Track API response time
- ✓ Monitor error rates
- ✓ Alert on 80% quota usage
- ✓ Track cache hit rate
- ✓ Monitor risk score distribution
