Are streaming APIs exactly-once? No. Delivery is at-least-once. This means messages may be delivered more than once, clients must be idempotent (handle duplicates), and you should use message IDs to deduplicate.Example deduplication:
Copy
Ask AI
seen_messages = set()for message in stream: message_id = message.get('id') if message_id in seen_messages: continue # Skip duplicate seen_messages.add(message_id) process_message(message)
Do streams always start with a snapshot? Yes. When you subscribe to a stream, the first message is a complete snapshot and subsequent messages are updates (deltas or new snapshots). You must apply the initial snapshot to establish state and process subsequent updates against that base state.Example:
Copy
Ask AI
Message 1: Snapshot of all open ordersMessage 2: Order 123 filled (delta)Message 3: Order 456 canceled (delta)Message 4: New order 789 opened (delta)
Market Data Streams: Order book updates, BBO (best bid/offer), instrument state changesOrder Streams: Order status changes, execution reports, order lifecycle eventsPosition Streams: Position changes, realized/unrealized P&L updates, risk metric changesDrop Copy Streams: Authoritative post-trade feed, executions and trades, settlement updates
Persistent connections: Streams use long-lived HTTP connections, not WebSockets (standard HTTP streaming), server pushes updates as they occur.Reconnection: Connections can drop due to network issues; implement automatic reconnection with exponential backoff.Example reconnection:
Some streams are resumable: Persist resume state (token or sequence number), resume from last processed event after disconnect, avoid missing events during disconnection.Example resume:
Copy
Ask AI
POST /v1/orders/subscribe{ "accountId": "your-account-id", "resumeToken": "last_processed_token"}
Not all streams support resume. Check API documentation for each endpoint.
Messages on a single stream are delivered in order.Messages across different streams may not be ordered relative to each other. If you need cross-stream ordering, use timestamps in messages, implement local ordering logic, and use sequence numbers where available.
Why is idempotency important? With at-least-once delivery, you may process the same message twice and your logic must handle duplicates gracefully.How to be idempotent: Track processed message IDs, use database unique constraints on IDs, design operations to be repeatable (e.g., “set to X” not “add Y”).Example idempotent order processing:
Copy
Ask AI
def process_order_update(order_update): order_id = order_update['orderId'] exec_id = order_update['execId'] # Try to insert execution try: db.insert_execution(exec_id, order_update) except UniqueConstraintError: # Already processed this execution return # Update order state db.update_order(order_id, order_update['status'])
Client-to-server messages: Limited to 20 messages per second, applies to requests you send (subscriptions, commands), does not apply to server-pushed updates.Connection limits: Maximum 10 concurrent streaming connections per account; plan your subscription strategy accordingly.
Some streams send periodic snapshots even if state hasn’t changed to help detect missed messages, allow clients to reconcile state, typically every few minutes. When you receive a snapshot, replace your entire local state with the snapshot; don’t try to merge or diff against previous state.
Missing messages: Possible causes include connection dropped (implement reconnection), resume state lost (persist resume tokens), at-least-once delivery issue (check for duplicates elsewhere). Solution: Use resumable streams and persist state.Duplicate messages: Expected behavior. Implement deduplication using message IDs.Stream stops sending updates: Check if the connection is still alive, send periodic heartbeats or test messages, implement connection timeout detection, reconnect if no messages received for X seconds.State inconsistency: If your local state doesn’t match server state, unsubscribe and resubscribe (forces new snapshot), reconcile with REST API query, or check for processing errors in your code.
Always handle reconnections: Network issues are inevitable. Auto-reconnect with backoff.Deduplicate messages: Track processed message IDs and skip duplicates.Persist resume state: Save tokens/sequence numbers to resume after restart.Monitor stream health: Detect stale connections and reconnect.Process snapshots correctly: Replace state, don’t merge.Use appropriate connection counts: Stay within the 10-connection limit.Handle snapshot + delta pattern: Apply initial snapshot, then process deltas.