Stock API Watchlists Can Share Requests Without Hiding Stale Prices
TickDB Research ·
Stock API Watchlists Can Share Requests Without Hiding Stale Prices
Summary: A stock watchlist can exhaust an API budget even when every user follows the same symbols. Where data permissions allow it, batching those symbols and sharing retrieval across viewers reduces duplicate upstream requests while preserving each record's timestamp. In a hypothetical case with 20 identical 120-symbol watchlists, batches of 50, and a five-second polling interval, independent polling needs 720 requests per minute; one shared collector needs 36, before retries and other traffic.

A stock API lets software request or receive stock-related data. In a watchlist, the application uses that interface to populate rows with prices and other available fields. The same data can support a portfolio overview or a research dashboard, but the API does not decide how often the screen should refresh or how the application should label an old observation.
Those decisions become visible as an app grows. If every open browser starts its own polling loop, upstream requests grow with the audience even when the requested symbols are identical. A shared collector can remove that duplication. It must also preserve data age: serving an old record quickly does not make the record current.
Count upstream requests before choosing a refresh interval
For polling, count the batches needed for one refresh cycle, then multiply by the cycles per minute. If 120 distinct symbols fit into batches of at most 50, each cycle needs three requests. A five-second interval gives 12 cycles per minute, or 36 requests per minute for one collector.
Twenty independent collectors doing the same work require 720 requests per minute. One collector serving those same viewers still needs 36 upstream requests per minute under these assumptions. The application must still deliver updates to its clients; sharing retrieval does not remove that downstream work.
The batch size has a concrete implementation example: TickDB provides a Ticker Snapshot endpoint that accepts up to 50 symbols per request. Its response includes the symbol, last traded price, and a timestamp; other market-data fields are conditional on the product, session, and availability. This makes it a useful example for a watchlist adapter, provided the selected plan and data permissions fit the application.
The calculation below is an offline planning tool. It uses synthetic identifiers, makes no API calls, and assumes all lists belong to one permitted sharing group with the same feed, fields, and refresh cadence.
from math import ceil, isfinite
def request_budget(watchlists, batch_size, interval_s):
if type(batch_size) is not int or batch_size <= 0:
raise ValueError("batch_size must be a positive integer")
if not isfinite(interval_s) or interval_s <= 0:
raise ValueError("interval_s must be positive and finite")
lists = [set(symbols) for symbols in watchlists]
union = set().union(*lists)
cycles_per_minute = 60 / interval_s
independent = sum(ceil(len(s) / batch_size) for s in lists)
shared = ceil(len(union) / batch_size)
return {
"independent_rpm": independent * cycles_per_minute,
"shared_rpm": shared * cycles_per_minute,
}
symbols = [f"DEMO_{i:03d}" for i in range(120)]
print(request_budget([symbols] * 20, 50, 5))
# {'independent_rpm': 720.0, 'shared_rpm': 36.0}
The function deduplicates symbols within each list and across the sharing group. For different watchlists, it uses their actual union rather than assuming every viewer follows the same stocks. Separate groups must be calculated separately.
These are steady-state average HTTP request counts, not a bill, a measured benchmark, or proof that a plan has enough capacity. They omit retries, startup requests, other endpoints, and provider-specific charging units. Short-window burst limits also matter: three simultaneous requests and three evenly spaced requests have the same average but different burst behavior.

Figure 1. Calculated example, not a performance test. Twenty viewers follow the same 120 symbols, with 50 symbols per request and a five-second polling interval. Counts exclude retries and other traffic; shared delivery assumes compatible permissions.
Share collection only across compatible requests
The collector should combine subscriptions or polling demand for the same data, then distribute the results to authorized viewers. Keep the provider credential on the server. Each browser connects to the application using its own authenticated session, and the application checks what that viewer may receive.
A cache key needs enough context to prevent unlike records from colliding. Include the instrument identity and relevant feed, session, and data-mode settings. Separate entitlement groups when their access differs. A delayed feed and a real-time feed should not become interchangeable because they use the same ticker string.
Request sharing is an application design choice. It does not itself establish permission to display or redistribute a provider's data. Confirm that the intended audience and delivery model are allowed before combining viewers into one sharing group.
For a polling implementation, keep one refresh operation in flight per shared batch. If a slow response is still pending, a new screen refresh should reuse the available cache or wait for that operation rather than start an identical upstream request. When the last viewer leaves, remove unused demand after a deliberate grace period. In an application with several server instances, coordinate collection so each instance does not recreate the same upstream workload.

Figure 2. Suggested application architecture using TickDB snapshots as the source. The collector, cache, and viewer authorization belong to the application. Sharing requires compatible data permissions; the diagram does not assert redistribution rights or measured performance.
A cache hit says nothing about market freshness
Keep the provider timestamp, the time your server received the record, and the time the browser rendered it as separate values. TickDB documents its snapshot timestamp in Unix milliseconds. Preserve that value and confirm its event meaning for the selected data before using it to measure market-data latency.
A local cache lifetime tells the application when to attempt another fetch. It does not guarantee that the next response will contain a newer market observation. Polling every second can return the same last-trade price repeatedly, especially when a stock is inactive or its trading session has ended.
Display wording should reflect what the application knows. “Last checked” can describe a successful fetch. “Data as of” can show the provider timestamp. “Refresh failed” can explain why an older value remains visible. Do not overwrite the original timestamp with the current browser time and label the result live.
Choose freshness thresholds for the field and session being displayed. An old last trade during a quiet period is different from a failed connection. A watchlist can retain the last available value while showing that updates are unavailable; a feature that needs fresher input can decline to use it. Missing optional fields should remain unavailable rather than becoming zero.
Streaming changes the workload but keeps the state problem
A WebSocket stream can replace repeated snapshot requests when the application needs ongoing updates. TickDB documents a ticker channel with symbol-level subscribe and unsubscribe commands. A shared server connection can maintain the union of current demand, subject to the provider's connection and subscription limits and the application's data permissions.
Receiving events and repainting the screen are separate operations. The application can maintain its latest record for each symbol while rendering the visible watchlist at a manageable cadence. That is appropriate for a latest-value display. It is not a substitute for retaining every event when the task is trade analysis, auditing, or another event-complete workflow.
A connected socket alone does not establish that every requested symbol is subscribed or current. Track subscription outcomes and connection health separately from each record's timestamp. After a disconnect, show the loss of updates and follow the provider's recovery behavior before declaring the view current again. A new snapshot restores a latest-value view; it does not reconstruct events missed during the interruption.
Handle limits without multiplying the load
TickDB's error documentation distinguishes rate limiting, exhausted quota, connection limits, and subscription limits. For its rate-limit error, the documented action is to wait for the Retry-After duration. A permissions error or exhausted quota requires a different response; repeatedly retrying it will not create access.
Make the shared collector responsible for retries. If every waiting browser retries on its own, one failed refresh can turn into a burst of duplicate upstream requests. Use bounded retries and jitter where appropriate, reserve capacity for other work, and keep a visible degraded state while updates are unavailable. A quota budget should leave room for recovery traffic rather than allocate every request to routine refreshes.
Open source does not remove the upstream limits
Open-source stock-data clients are available. Databento, for example, publishes an open-source Python client for its market-data service. Such software can make integration easier to inspect and extend, but the client's license does not define the service's data access, request limits, or display permissions.
For a watchlist, inspect whether a client batches symbols, retries automatically, or creates one connection per instance. A wrapper can simplify a request while still duplicating the same work across viewers. The application remains responsible for its total demand and for how it presents cached values.
Before shipping, test two viewers requesting the same data at once, a refresh that takes longer than its interval, an omitted symbol, and an upstream limit response. Confirm that duplicate work stays controlled and that old values keep their original timestamps. The result should be a watchlist whose request volume and freshness labels remain understandable as more people open it.
Documentation basis: TickDB Ticker Snapshot, Real-Time Quotes and Error Codes, and the Databento Python client repository, checked November 5, 2026. The request-volume example is calculated from stated assumptions, not measured on a live service.