Performance degradation in Binance Pro watch_trades() under high message rates · Issue #30944 · ccxt/ccxt · GitHub
Skip to content

Performance degradation in Binance Pro watch_trades() under high message rates #30944

Open

Description

@algosfox

Operating System

Ubuntu 24.04

Programming Language

Python

CCXT Version

4.5.88

Description

Problem

I am using CCXT Pro with Binance USD-M Futures and consuming trade ticks via watch_trades().

Under low message rates, the data is delivered without noticeable delays. However, when the incoming trade rate increases to thousands of ticks, significant delays appear between WebSocket message reception inside the library and delivery of the corresponding trades to the application through watch_trades().

This is not exchange-to-WebSocket network latency. The delay occurs inside the CCXT processing pipeline under high load.

To investigate this, I implemented an alternative WebSocket consumer with an interface similar to watch_trades(). In comparative tests, it delivered trade ticks approximately 3–5 times faster under the tested conditions.

Questions

  • Is there a way to optimize the built-in watch_trades() processing path for high message rates?
  • Could the bottleneck be related to synchronous message processing, trade-cache operations, or batch extraction?
  • Would it make sense to provide an optional high-throughput mode that prioritizes low delivery latency, alongside the existing behavior?

I can share further benchmark details to help identify the bottleneck.

Activity

  1. algosfox commented on Oct 21, 2026

    @algosfox
    Author

    Additional findings: CCXT Pro vs. a lightweight WebSocket consumer

    I reviewed the trade-delivery path in CCXT Pro and compared it with my alternative implementation.

    CCXT Pro processing path:

    # Client.receive_loop()
    while len(self.buffer) > 1:
        message, size = self.buffer.popleft()
        size_delta += size
        self.handle_message(message)

    The buffered messages are processed synchronously in a loop. The subsequent path includes JSON decoding, Binance-specific message routing, trade normalization, ArrayCache updates and batch extraction in watch_trades().

    Under high message rates, I suspect that synchronous processing and/or cache extraction may cause a growing backlog and delay delivery to the consumer, potentially affecting other tasks sharing the event loop.

    My alternative implementation:

    async def watch_trades(self, symbol):
        await self._ensure_symbol(symbol)
        await self.start()
        state = self._streams[symbol]
        # Wait for data, then drain the symbol's queue.
        ...

    A shared aiohttp WebSocket transport handles incoming trade messages, parses the required fields and puts normalized trades into per-symbol asyncio.Queue instances. The consumer retrieves available trades directly from its queue, without CCXT's trade-cache and slicing path.

    In my comparative tests, this implementation delivered ticks approximately 3–5 times faster under the tested conditions.

    This suggests that the difference may lie in message processing, buffering or batch delivery rather than network latency alone. The exact contribution of each CCXT stage still needs to be isolated by profiling.

    Could the receive-buffer processing and ArrayCache extraction paths be reviewed for high-throughput workloads? Would an optional low-latency mode with a lighter processing path be feasible?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions