When a quant researcher at a systematic fund says "our system handles latency," they rarely mean milliseconds. They mean the distribution — the P50 where half the requests fly through, the P99 where every tenth percentile matters, and the tail end where a single outlier can blow up a fill rate calculation or trigger a cascade of missed opportunities. Latency is not a single number. It is a probability distribution, and the SLA is the contract that defines where the distribution's cutoff lives.
This article opens TickDB's latency specification from the inside out. It covers the official SLA terms, decomposes what P50/P95/P99/P999 actually mean for your trading logic, examines how the system holds up under real-market stress conditions — earnings releases, index rebalancing windows, macro surprise events — and provides production-grade code you can run today to measure your own end-to-end latency from API request to response body.
Why Latency SLA Is a Quant Researcher's Problem, Not Just an Infrastructure Problem
Most data vendors publish a latency number as a marketing bullet. "Sub-100ms" appears on landing pages the way "cloud-native" appeared everywhere in 2019. The number is selected to sound good. It is rarely tested under the conditions where latency actually destroys a strategy.
Consider the scenario that separates infrastructure theater from genuine reliability. A mean-reversion strategy on earnings night watches the post-release order book. It needs the depth snapshot within 50 ms of the release timestamp to catch the initial liquidity vacuum. If the API responds in 200 ms on a normal day but spikes to 1,400 ms during the earnings window — when every data consumer is hammering the same endpoint simultaneously — the strategy misses the window entirely. The SLA number does not matter if the P99 collapses under correlated load.
TickDB's SLA structure addresses this through a tiered latency commitment tied to data type and market. Understanding which tier applies to your use case is the first engineering decision in this article.
Official SLA Terms: What TickDB Commits To
TickDB publishes latency commitments at two levels: a general API response SLA and a per-data-type SLA that reflects the underlying infrastructure differences between REST polling and WebSocket push delivery.
General API Response SLA
| Metric | Commitment | Applicable endpoints |
|---|---|---|
| P50 latency | < 50 ms | All authenticated REST endpoints |
| P95 latency | < 150 ms | All authenticated REST endpoints |
| P99 latency | < 300 ms | All authenticated REST endpoints |
| Availability | 99.9% uptime | Platform-wide, excluding scheduled maintenance |
These numbers reflect the server-side processing time from receipt of a valid authenticated request to the transmission of the response body. They do not include network transit time between the client and TickDB's edge nodes, TLS handshake overhead, or any client-side processing. For readers operating from co-location facilities in Ashburn, Virginia — the primary TickDB region — network transit adds approximately 1–3 ms. For readers connecting from Singapore, Tokyo, or European data centers, expect 80–180 ms of round-trip transit on top of the server-side figures.
WebSocket Push Latency
For real-time data streams delivered via WebSocket, the latency profile differs fundamentally from REST polling. The commit is not a response time but a push delay — the interval between TickDB's internal market data receipt and the transmission of the update to the connected client.
| Data type | P50 push delay | P99 push delay | Notes |
|---|---|---|---|
depth (order book) |
< 30 ms | < 80 ms | US equities L1; HK L1–L10; Crypto L1–L10 |
ticker (quote) |
< 25 ms | < 70 ms | Varies by market |
trades (trade flow) |
< 20 ms | < 60 ms | HK and crypto only; not available for US equities or A-shares |
kline (OHLCV bar update) |
< 40 ms | < 100 ms | Current bar update; closed bars via REST |
The critical distinction is that the WebSocket push delay measures the pipeline from exchange feed ingestion to your client — not the round-trip for a request you send. If your strategy subscribes to the depth channel, TickDB is pushing updates to you. The 80 ms P99 means that 99% of order book updates arrive within 80 ms of TickDB receiving them. Your strategy's reaction time is bounded by your own processing logic after that point.
Latency Distribution: Reading the Percentiles Correctly
Percentile metrics are commonly misunderstood in a way that can cost a quant researcher real money. Here is the precise definition applied to TickDB's SLA.
P99 latency of 300 ms means that 99 out of 100 authenticated API requests complete within 300 ms. It does not mean that every request takes 300 ms. It does not even mean that 1% of requests take more than 300 ms — that would be P99+1. The 300 ms figure is the ceiling for the 99th percentile. The actual distribution might look like this:
| Percentile | Observed latency (REST API, Ashburn) |
|---|---|
| P50 | 38 ms |
| P75 | 67 ms |
| P90 | 121 ms |
| P95 | 148 ms |
| P99 | 287 ms |
| P99.9 | 410 ms |
Notice that P99.9 — one request in a thousand — sits above the SLA ceiling. This is by design. No SLA commits to the 99.9th percentile without a separate enterprise contract. For production trading strategies, understanding where your percentile lives relative to your execution deadline is the engineering problem. A market-making strategy with a 200 ms execution horizon cares deeply about P99. A swing trade evaluated hourly can tolerate P99 easily but may care about P50 stability.
The distribution shape also reveals regime dependence. On quiet days — typical trading hours without major macro events — the distribution is tight and left-skewed. The P50 might sit at 32 ms, P99 at 210 ms. During the earnings window, the same endpoint serving the same request shape might show a P50 of 55 ms and P99 of 480 ms. Both figures are within the published SLA (300 ms for P99), but the regime shift changes the risk profile for latency-sensitive strategies. Your backtest that used clean, low-volatility market data will not capture this. Your production monitoring must.
Extreme Market Conditions: Stress Performance
The SLA's 99.9% availability commitment covers platform uptime but does not specify latency behavior during market stress events. This section documents what the data shows under four canonical stress scenarios, drawn from observed production behavior during major market events in 2024 and 2025.
Earnings Releases
During the 30-second window surrounding a high-profile earnings release (e.g., NVDA, AAPL, MSFT), the kline and ticker endpoints experience a 2.5–4x increase in request volume. Observed P99 latency under this load:
- REST
klineendpoint: P99 rises from ~280 ms (baseline) to ~650 ms during peak load, then recovers within 90 seconds. - WebSocket
depthpush delay: P99 increases from ~80 ms to ~140 ms. The queue depth on TickDB's internal processing buffers grows but does not overflow.
The key observation: latency increases, but the system remains responsive. Requests do not time out. The P99 spike is a burst, not a sustained degradation.
Pre- and Post-Market Sessions
TickDB's real-time channels remain active during US equity pre-market (4:00–9:30 AM ET) and after-hours (4:00–8:00 PM ET) sessions. These sessions have lower overall liquidity but higher relative volatility per trade. Observed behavior:
depthpush delay P99: ~95 ms (vs. 80 ms during regular hours).tradesvolume: significantly lower, which reduces queue contention and actually improves P50 latency by approximately 15%.
Index Rebalancing Windows
During the 15-minute windows surrounding S&P 500 and Russell 2000 quarterly rebalancing, order book dynamics change materially — large institutional orders flood specific tickers, bid-ask spreads widen, and liquidity temporarily concentrates. TickDB's observed behavior:
- P99 latency for
depthsnapshots increases to ~110 ms (vs. 80 ms baseline). - No measurable increase in error rates or 5xx responses.
High-Volatility Crypto Sessions
For crypto markets, the stress scenario is not earnings but leverage cascade events — rapid liquidations triggering cascade selling. Observed during the April 2025 BTC flash dip:
tradespush delay P99: ~95 ms (vs. 60 ms baseline).depthpush delay P99: ~130 ms (vs. 80 ms baseline).- REST polling P99: ~420 ms (vs. 280 ms baseline).
The pattern across all stress scenarios is consistent: latency degrades by 40–80% under peak correlated load, but the system remains functional. No SLA violations (defined as sustained P99 > 300 ms for more than 60 consecutive seconds) were observed during any stress event in the 2024–2025 sample.
How to Verify Your Latency: A Production-Grade Measurement Client
Theory is insufficient. Every quant team operating TickDB in production should maintain an active latency monitor that measures end-to-end request-to-response time from their own infrastructure. The following Python client implements production-grade latency measurement with percentile tracking, alerting thresholds, and structured logging.
import os
import time
import statistics
import json
import requests
from datetime import datetime, timezone
from collections import deque
# ⚠️ For production HFT workloads, consider using asyncio/aiohttp for non-blocking measurement.
class TickDBLatencyMonitor:
"""
Production-grade latency monitor for TickDB REST API.
Measures end-to-end latency (request sent to response body received)
from the client's network location. Tracks P50, P95, P99, P99.9.
"""
def __init__(self, api_key: str, symbol: str = "BTC.USDT", interval: str = "1m"):
self.api_key = api_key
self.symbol = symbol
self.interval = interval
self.latencies = deque(maxlen=2000) # Rolling window of 2000 samples
self.error_count = 0
self.timeout = (3.05, 10) # Connect timeout, read timeout
def _build_headers(self) -> dict:
"""Load API key from environment variable — never hardcode credentials."""
key = self.api_key or os.environ.get("TICKDB_API_KEY")
if not key:
raise ValueError("TICKDB_API_KEY environment variable is not set")
return {"X-API-Key": key}
def measure_request(self, retries: int = 3) -> dict:
"""
Execute a single kline request and record end-to-end latency.
Returns a dict with latency_ms, status_code, timestamp, and any error.
"""
url = "https://api.tickdb.ai/v1/market/kline"
params = {"symbol": self.symbol, "interval": self.interval, "limit": 100}
for attempt in range(retries):
start = time.perf_counter()
try:
response = requests.get(
url,
headers=self._build_headers(),
params=params,
timeout=self.timeout
)
latency_ms = (time.perf_counter() - start) * 1000
if response.status_code == 200:
data = response.json()
code = data.get("code", 0)
if code == 0:
self.latencies.append(latency_ms)
return {
"latency_ms": round(latency_ms, 2),
"status": "success",
"timestamp": datetime.now(timezone.utc).isoformat(),
"retry_attempt": attempt
}
elif code == 3001:
retry_after = int(response.headers.get("Retry-After", 5))
# Rate limit hit — respect the header and retry
time.sleep(retry_after)
continue
else:
self.error_count += 1
return {
"latency_ms": round(latency_ms, 2),
"status": "api_error",
"error_code": code,
"timestamp": datetime.now(timezone.utc).isoformat()
}
else:
self.error_count += 1
return {
"latency_ms": round(latency_ms, 2),
"status": "http_error",
"http_code": response.status_code,
"timestamp": datetime.now(timezone.utc).isoformat()
}
except requests.exceptions.Timeout:
self.error_count += 1
return {
"latency_ms": None,
"status": "timeout",
"timestamp": datetime.now(timezone.utc).isoformat()
}
except requests.exceptions.ConnectionError:
# Exponential backoff with jitter on connection failures
delay = min(1.0 * (2 ** attempt), 30.0)
jitter = statistics.uniform(0, delay * 0.1)
time.sleep(delay + jitter)
continue
self.error_count += 1
return {
"latency_ms": None,
"status": "max_retries_exceeded",
"timestamp": datetime.now(timezone.utc).isoformat()
}
def percentile(self, p: float) -> float | None:
"""Calculate the p-th percentile from the rolling latency sample."""
if not self.latencies:
return None
sorted_latencies = sorted(self.latencies)
k = (len(sorted_latencies) - 1) * (p / 100)
f = int(k)
c = f + 1 if f < len(sorted_latencies) - 1 else f
return round(sorted_latencies[f] + (k - f) * (sorted_latencies[c] - sorted_latencies[f]), 2)
def summary(self) -> dict:
"""Return a snapshot of current latency statistics."""
if not self.latencies:
return {"status": "insufficient_data"}
total_requests = len(self.latencies) + self.error_count
error_rate = self.error_count / total_requests if total_requests > 0 else 0
return {
"sample_size": len(self.latencies),
"total_requests": total_requests,
"error_count": self.error_count,
"error_rate_pct": round(error_rate * 100, 3),
"p50_ms": self.percentile(50),
"p75_ms": self.percentile(75),
"p95_ms": self.percentile(95),
"p99_ms": self.percentile(99),
"p999_ms": self.percentile(99.9),
"min_ms": round(min(self.latencies), 2),
"max_ms": round(max(self.latencies), 2),
"mean_ms": round(statistics.mean(self.latencies), 2),
"stddev_ms": round(statistics.stdev(self.latencies), 2) if len(self.latencies) > 1 else 0,
"timestamp": datetime.now(timezone.utc).isoformat()
}
def run_continuous(self, interval_seconds: int = 5, duration_seconds: int = 300):
"""
Run continuous latency monitoring for a specified duration.
Prints a summary report every `interval_seconds`.
"""
start_time = time.monotonic()
print(f"[{datetime.now(timezone.utc).isoformat()}] Latency monitor started. "
f"Running for {duration_seconds}s with {interval_seconds}s sampling interval.")
print("-" * 80)
while time.monotonic() - start_time < duration_seconds:
result = self.measure_request()
if result["status"] == "success":
print(f"[{result['timestamp']}] OK {result['latency_ms']} ms")
else:
print(f"[{result['timestamp']}] ERR {result['status']}")
time.sleep(interval_seconds)
# Print summary every 10 samples
if len(self.latencies) > 0 and len(self.latencies) % 10 == 0:
summary = self.summary()
print(f"\n--- Latency Summary (n={summary['sample_size']}) ---")
print(f" P50: {summary['p50_ms']} ms | P95: {summary['p95_ms']} ms | P99: {summary['p99_ms']} ms")
print(f" Error rate: {summary['error_rate_pct']}% | Max: {summary['max_ms']} ms\n")
final = self.summary()
print("\n=== Final Report ===")
print(json.dumps(final, indent=2))
# Entry point for standalone execution
if __name__ == "__main__":
monitor = TickDBLatencyMonitor(
api_key=os.environ.get("TICKDB_API_KEY"),
symbol="BTC.USDT",
interval="1m"
)
# Run for 5 minutes, sampling every 5 seconds = 60 samples
monitor.run_continuous(interval_seconds=5, duration_seconds=300)
What This Monitor Validates
The client above measures end-to-end client-side latency — the full round-trip from your request being sent to your client receiving and processing the response. This is the metric that matters for your strategy's decision loop, and it is the metric that differs from the server-side SLA numbers in three important ways:
- Your network path adds transit time. If you are in Frankfurt querying a US-hosted API, expect 120–160 ms of round-trip transit regardless of how fast TickDB processes the request.
- TLS handshake overhead adds 5–15 ms on the first request of a session (mitigated by connection keep-alive).
- Your processing logic after receiving the response body — JSON deserialization, data transformation, signal computation — is included in the measurement if you add it to the timer.
To isolate server-side latency from network overhead, run the monitor from a cloud instance in the same region as TickDB (Ashburn, Virginia for US equity data). Compare the results to your own infrastructure to establish a baseline network overhead you can subtract from future measurements.
Understanding the SLA Fine Print
Every SLA document contains terms that practitioners routinely overlook until they matter. Here are the four clauses most likely to affect your use of TickDB's latency commitments.
Measurement methodology. TickDB measures latency from the point its edge server receives the request to the point it begins transmitting the response body. This excludes TLS termination time and the client's own TCP connection setup. If you are measuring from your application layer (which is the correct approach for strategy latency budgets), your observed numbers will be 2–8 ms higher due to TLS overhead alone.
Excluded events. The 99.9% availability SLA explicitly excludes scheduled maintenance windows, which are announced at least 72 hours in advance via the TickDB status page and API status endpoint. Latency degradation during announced maintenance windows does not constitute an SLA breach.
Rate limit behavior under stress. When the 3001 rate limit code is returned, the server-side processing time for that request is not counted toward the latency SLA. The retry is a new request. This means that a latency-sensitive strategy hitting the rate limit will observe a blocking delay equal to the Retry-After value, which may be 5–60 seconds. Design your request patterns to stay within rate limits during critical trading windows.
Enterprise SLA upgrades. The standard SLA (P99 < 300 ms, 99.9% availability) applies to Professional tier accounts. Enterprise tier contracts offer P99 < 150 ms commitments, dedicated infrastructure, and SLA credits for breaches — a meaningful distinction for a market-making strategy where a 150 ms gap in order book data costs realPnL.
Latency Budget Allocation for Strategy Design
If you are building a real-time strategy that consumes TickDB data, you need to allocate your total latency budget before you select your data vendor. The budget is the maximum time available from "market state changes" to "my strategy has acted on it." Every millisecond consumed by data delivery, network transit, computation, and order submission must fit within this budget.
| Latency budget component | Typical allocation (market-making) | Typical allocation (daily rebalance) |
|---|---|---|
| Network transit (client → exchange) | 0.5–2 ms | 50–200 ms |
| Data API response time | < 50 ms (P99) | < 300 ms (P99) |
| Strategy computation | 5–20 ms | 500–2000 ms |
| Order routing and exchange acknowledgment | 2–10 ms | 100–500 ms |
| Total budget consumed | ~60–80 ms | ~1,150–3,000 ms |
For a market-making strategy requiring sub-100 ms total latency, TickDB's REST API at P50 (38 ms) is usable but tight. The WebSocket depth push (P99: 80 ms) is the appropriate channel — it delivers order book updates proactively, removing the request round-trip from your critical path entirely. Your strategy's computation must complete within the remaining budget after the push arrives.
For a daily rebalance strategy, the REST API is more than sufficient. The P99 of 300 ms is negligible relative to a 30-minute rebalancing window.
Comparing Latency Across Market Data Providers
The following table provides an objective latency comparison across major retail-accessible market data APIs. Figures are drawn from each vendor's published documentation and from community-reported benchmarks. Values represent server-side P99 latency for REST endpoints under normal load conditions.
| Metric | TickDB | Polygon.io | Alpaca | Databento |
|---|---|---|---|---|
| REST P99 latency | < 300 ms | < 500 ms | < 400 ms | < 200 ms |
| WebSocket push delay (quotes) | < 70 ms (P99) | < 100 ms (P99) | < 120 ms (P99) | < 50 ms (P99) |
| Historical OHLCV depth | 10+ years (US equities) | 5+ years (US equities) | 2+ years (US equities) | 10+ years (US equities) |
| Order book depth | L1 US / L1–L10 HK+Crypto | L1 US | L1 US | L1–L50 |
| Rate limit (free tier) | 600 req/min | 100 req/min | 200 req/min | Variable |
| SLA guarantee | Yes (Professional+) | No public SLA | No public SLA | Yes (Enterprise) |
A few notes on this comparison. Databento's P99 latency of < 200 ms on the REST endpoint is competitive with TickDB's < 300 ms, but Databento's free tier is significantly more restrictive on rate limits. Polygon and Alpaca do not publish SLA guarantees, which means the latency figures are marketing numbers rather than contractual commitments. For systematic trading where latency reproducibility matters, a published SLA is substantially more valuable than a marketing claim.
Deploying Latency Monitoring in Your Stack
For teams operating at institutional scale, the single-threaded Python monitor above is a starting point, not a final state. The following deployment recommendations scale from individual researchers to multi-strategy quant funds.
Individual researcher (free tier). Run the latency monitor script on a cron job every 15 minutes. Store results in a local SQLite database. Plot P50 and P99 over time in a Grafana dashboard. Set a P99 alert threshold at 400 ms — above this, open a support ticket.
Team deployment (Professional tier). Deploy the monitor as a sidecar container alongside your strategy containers. Emit latency metrics in Prometheus format. Alert on P99 > 350 ms for more than 60 seconds. Use the alert to trigger a fallback data source if TickDB latency exceeds your strategy's tolerance.
Institutional deployment (Enterprise tier). Negotiate a dedicated measurement endpoint with TickDB's enterprise team. This endpoint provides server-side latency telemetry without the network path ambiguity, enabling precise attribution of latency deviations. Co-locate your monitoring agent in the same data center region.
The Takeaway: Latency Is a Distribution, Not a Number
TickDB's P99 < 300 ms SLA tells you the ceiling for 99% of your requests under normal conditions. What it does not tell you — and what you must measure yourself — is your own end-to-end latency from your own network location, under your own load patterns, during the specific market conditions that affect your strategy.
The practical framework is this: establish your latency budget before you select a data vendor. If your strategy requires action within 100 ms of a market event, the REST API is insufficient regardless of its SLA — you need WebSocket push delivery. If your strategy operates on a 5-minute resolution, the REST P99 is essentially irrelevant and your selection criteria should favor data depth and historical coverage instead.
Measure continuously. The SLA is a floor, not a ceiling. Your own monitoring will reveal regime-dependent latency behavior that no vendor documentation can capture, and those observations will drive the architectural decisions that keep your strategy live when the market moves fastest.
Next Steps
If you want to measure your own latency right now, download the monitoring script above, set your TICKDB_API_KEY environment variable, and run it for 30 minutes during your next trading session. The data you collect is the only latency number that actually applies to your system.
If you are building a latency-sensitive strategy and need sub-100 ms data delivery, switch from REST polling to the TickDB WebSocket channels. The depth and ticker push channels eliminate the request round-trip from your critical path entirely.
If you need a contractual P99 < 150 ms commitment with SLA credits, reach out to enterprise@tickdb.ai for Enterprise tier pricing and dedicated infrastructure options.
If you are evaluating TickDB for the first time, sign up at tickdb.ai — no credit card required for the free tier. Your free API key gives you 600 requests per minute, enough to run the latency monitor and validate the SLA against your own infrastructure before committing to a paid plan.
This article does not constitute investment advice. Markets involve risk; past performance does not guarantee future results. Latency figures reflect server-side SLA commitments and observed production data; your end-to-end latency will vary based on network path, client infrastructure, and market conditions.