Skip to main content

Connection Management

Best practices for maintaining reliable WebSocket connections.

Subscription Management

Subscribe

Subscribe to one or multiple streams:
{
  "method": "subscribe",
  "subscription": [
    {"type": "ticker", "symbol": "BTC-USDC"},
    {"type": "trades", "symbol": "ETH-USDC"},
    {"type": "account", "user": "FuueqefENiGEW6uMqZQgmwjzgpnb85EgUcZa5Em4PQh7"}
  ]
}
Response:
{
  "channel": "subscriptionResponse",
  "subscriptions_ids": [101, 102, 103]
}

Unsubscribe

Unsubscribe using the subscription ID:
{
  "method": "unsubscribe",
  "subscription_id": 101
}

Reconnection Strategy

WebSocket connections can drop due to network issues. Always implement reconnection logic.
class BulkWebSocket {
  constructor(url) {
    this.url = url;
    this.ws = null;
    this.reconnectDelay = 1000;
    this.maxReconnectDelay = 30000;
    this.subscriptions = [];
  }
  
  connect() {
    this.ws = new WebSocket(this.url);
    
    this.ws.on('open', () => {
      console.log('Connected');
      this.reconnectDelay = 1000; // Reset delay
      this.resubscribe();
    });
    
    this.ws.on('message', (data) => {
      const message = JSON.parse(data);
      this.handleMessage(message);
    });
    
    this.ws.on('close', () => {
      console.log('Disconnected. Reconnecting...');
      this.reconnect();
    });
    
    this.ws.on('error', (error) => {
      console.error('WebSocket error:', error);
    });
  }
  
  reconnect() {
    setTimeout(() => {
      console.log(`Reconnecting in ${this.reconnectDelay}ms...`);
      this.connect();
      
      // Exponential backoff
      this.reconnectDelay = Math.min(
        this.reconnectDelay * 2,
        this.maxReconnectDelay
      );
    }, this.reconnectDelay);
  }
  
  subscribe(subscription) {
    this.subscriptions.push(subscription);
    
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({
        method: 'subscribe',
        subscription: [subscription]
      }));
    }
  }
  
  resubscribe() {
    if (this.subscriptions.length > 0) {
      this.ws.send(JSON.stringify({
        method: 'subscribe',
        subscription: this.subscriptions
      }));
    }
  }
  
  handleMessage(message) {
    // Handle different message types
    console.log('Received:', message);
  }
}

// Usage
const ws = new BulkWebSocket('wss://exchange-wss.bulk.trade');
ws.connect();
ws.subscribe({ type: 'ticker', symbol: 'BTC-USDC' });

Heartbeat / Ping-Pong

Keep the connection alive with periodic pings.
// Send ping every 30 seconds
setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.ping();
  }
}, 30000);

ws.on('pong', () => {
  console.log('Received pong');
});

Rate Limits

Connection Limits
  • Maximum 100 subscriptions per connection
  • Maximum 1000 messages per second
  • Exceeding limits will result in disconnection
If you need more subscriptions, open multiple connections.

Best Practices

Network issues are inevitable. Your application should automatically reconnect with exponential backoff.
After reconnecting, you must resubscribe to all channels. Store your subscription list.
Messages may arrive out of order during high load. Use timestamps and sequence numbers.
If no message is received for 60 seconds, consider the connection stale and reconnect.
Enable per-message deflate for bandwidth savings on high-frequency streams.
Use one connection for market data and another for trading to avoid mixing concerns.

Connection States

Monitor connection state to handle different scenarios:
StateDescriptionAction
CONNECTINGInitial connectionWait for open event
OPENConnected and readyCan send/receive messages
CLOSINGConnection closingStop sending messages
CLOSEDConnection closedReconnect if needed

Error Codes

Common WebSocket close codes:
CodeReasonAction
1000Normal closureNo action needed
1001Going awayReconnect
1002Protocol errorCheck message format
1003Unsupported dataCheck message content
1006Abnormal closureReconnect
1008Policy violationCheck rate limits
1011Server errorRetry with backoff

Monitoring Connection Health

Implement health checks to detect stale connections:
class ConnectionMonitor {
  constructor(ws, timeout = 60000) {
    this.ws = ws;
    this.timeout = timeout;
    this.lastMessage = Date.now();
    this.checkInterval = null;
  }
  
  start() {
    // Update timestamp on every message
    this.ws.on('message', () => {
      this.lastMessage = Date.now();
    });
    
    // Check health every 10 seconds
    this.checkInterval = setInterval(() => {
      const timeSinceLastMessage = Date.now() - this.lastMessage;
      
      if (timeSinceLastMessage > this.timeout) {
        console.warn('Connection stale, reconnecting...');
        this.ws.close();
      }
    }, 10000);
  }
  
  stop() {
    if (this.checkInterval) {
      clearInterval(this.checkInterval);
    }
  }
}

// Usage
const monitor = new ConnectionMonitor(ws);
monitor.start();

Multiple Connections

For high-throughput applications, consider using multiple connections:
// Connection 1: Market data
const marketDataWs = new WebSocket('wss://exchange-wss.bulk.trade');
marketDataWs.on('open', () => {
  marketDataWs.send(JSON.stringify({
    method: 'subscribe',
    subscription: [
      { type: 'ticker', symbol: 'BTC-USDC' },
      { type: 'trades', symbol: 'BTC-USDC' }
    ]
  }));
});

// Connection 2: Account updates
const accountWs = new WebSocket('wss://exchange-wss.bulk.trade');
accountWs.on('open', () => {
  accountWs.send(JSON.stringify({
    method: 'subscribe',
    subscription: [
      { type: 'account', user: PUBLIC_KEY }
    ]
  }));
});

// Connection 3: Trading
const tradingWs = new WebSocket('wss://exchange-wss.bulk.trade');
// Use this for order placement/cancellation

Testing Connection

Test your WebSocket connection with a simple script:
const WebSocket = require('ws');

const ws = new WebSocket('wss://exchange-wss.bulk.trade');

ws.on('open', () => {
  console.log('✓ Connected successfully');
  
  // Test subscription
  ws.send(JSON.stringify({
    method: 'subscribe',
    subscription: [{ type: 'ticker', symbol: 'BTC-USDC' }]
  }));
  
  setTimeout(() => {
    console.log('Test complete');
    ws.close();
  }, 5000);
});

ws.on('message', (data) => {
  console.log('✓ Received message:', data.toString());
});

ws.on('error', (error) => {
  console.error('✗ Error:', error);
});

ws.on('close', () => {
  console.log('✓ Connection closed');
});