Skip to content

[Polymarket] Add opt-in pruning for inactive Polymarket instrument state #3945

@fedoraiver

Description

@fedoraiver

Summary

Add an opt-in prune_inactive_instruments setting to PolymarketDataClientConfig.

When enabled, the Polymarket data client prunes per-instrument market data state after the last active market data subscription for an instrument has been removed.

The intended use case is long-running processes which dynamically subscribe to many short-lived Polymarket markets, for example recurring prediction markets where instruments are opened, streamed briefly, then closed and never used again.

Problem

PolymarketDataClient keeps several per-instrument caches while streaming live market data:

  • order_books
  • last_quotes
  • instruments
  • token_meta

For static instrument universes this is fine. For dynamic Polymarket workloads, especially short-duration markets, the client can discover and stream a large number of instruments over time. After market data subscriptions are removed, the instrument may no longer be useful to the process, but its cached state remains in memory.

In a 24/7 service, this means memory can grow with the number of historical instruments seen by the client instead of the number of currently active instruments.

Proposal

Add a new config field:

pub struct PolymarketDataClientConfig {
    // ...
    /// Whether to prune per-instrument market data caches after all market data
    /// subscriptions are removed.
    #[builder(default)]
    pub prune_inactive_instruments: bool,
    // ...
}

Default: false.

This preserves current behavior unless the user explicitly opts in.

Expose the same option through the Python config constructor:

PolymarketDataClientConfig(
    # ...
    prune_inactive_instruments=True,
)

Behavior

After each market data unsubscribe path:

  • unsubscribe_book_deltas
  • unsubscribe_quotes
  • unsubscribe_trades

the client checks whether the instrument still has any active market data subscriptions:

active_quote_subs.contains(&instrument_id)
    || active_delta_subs.contains(&instrument_id)
    || active_trade_subs.contains(&instrument_id)

If prune_inactive_instruments is false, cleanup is skipped entirely.

If the option is enabled and no active market data subscription remains, the client removes:

order_books.remove(&instrument_id);
last_quotes.remove(&instrument_id);
instruments.remove(&instrument_id);
token_meta.remove(&token_id);

The implementation resolves the token id from the live instrument cache when possible, and falls back to scanning token_meta by instrument_id when needed.

ws_open_tokens is intentionally not pruned by this cleanup path. WebSocket subscribe/unsubscribe state is reconciled separately by the existing websocket subscription logic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    RFCA request for comment

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions