Skip to main content

Concurrent Stream Limits

Your Odyssey plan includes a limit on the number of concurrent interactive streams you can run simultaneously. This limit is displayed in your Developer Portal dashboard. For example, a Free tier account allows up to 5 concurrent streams. This means you can have 5 active interactive sessions running at the same time across all your applications and devices.

Why My Concurrent Count Seems Higher Than Expected

You may occasionally notice that your concurrent stream count appears higher than the number of streams you believe are active. This is typically caused by dangling sessions—sessions that were not properly closed.
If you’re consistently hitting your concurrent limit due to dangling sessions, try implementing proper disconnect handling in your application (see best practices below).

Common Causes of Dangling Sessions

  1. Browser crashes or tab closures: If you close a browser tab without properly disconnecting, the session may remain active on our servers until it times out.
  2. Network interruptions: Sudden network disconnections (Wi-Fi drops, mobile network switches) can prevent the disconnect signal from reaching our servers.
  3. Application crashes: If your application crashes or is force-quit, it may not have a chance to send the disconnect signal.
  4. Hot Module Replacement (HMR): Development tools like Vite, Webpack, and Next.js use HMR to update your code without a full page reload. When a component that holds an Odyssey connection is replaced, the old connection may not be properly cleaned up, leaving orphaned sessions.
  5. Development restarts: Restarting your dev server (Ctrl+C and restart) without proper cleanup can leave sessions open on the server side.
  6. Multiple browser tabs: Opening the same application in multiple tabs can create multiple sessions, which may not all be cleaned up when you close the window.

How Dangling Sessions Are Resolved

Odyssey automatically cleans up stale sessions through a background process:
  • Sessions that haven’t sent a heartbeat within the timeout window are marked as stale
  • Stale sessions are automatically terminated and won’t count against your concurrent limit
  • This cleanup process runs continuously, typically resolving dangling sessions within a few minutes

Best Practices for Clean Session Management

Always Disconnect When Done

Call the disconnect method when your user leaves or when the session is no longer needed:
// Clean up when component unmounts or user navigates away
window.addEventListener('beforeunload', () => {
  odyssey.disconnect();
});

// Or in React with useEffect cleanup
useEffect(() => {
  return () => {
    odyssey.disconnect();
  };
}, []);

Handle Page Visibility Changes

For web applications, consider pausing or disconnecting when the user switches tabs:
document.addEventListener('visibilitychange', () => {
  if (document.hidden) {
    // Optionally disconnect or pause when tab is hidden
    odyssey.disconnect();
  }
});

Implement Reconnection Logic

If your application needs to maintain long-running sessions, implement reconnection logic that properly cleans up the old session:
async function reconnect() {
  // Always disconnect the old session first
  await odyssey.disconnect();

  // Then establish a new connection
  await odyssey.connect(config);
}

Handle Hot Module Replacement (HMR)

HMR is one of the most common causes of dangling sessions during development. When your bundler (Vite, Webpack, Next.js) hot-reloads a component, the previous instance’s cleanup function may not run correctly, leaving WebRTC connections open.
import { useEffect, useRef } from 'react';
import { Odyssey } from '@odysseyml/odyssey';

function VideoStream() {
  // Use a ref to persist the client across HMR
  const clientRef = useRef<Odyssey | null>(null);

  useEffect(() => {
    // Create client only if one doesn't exist
    if (!clientRef.current) {
      clientRef.current = new Odyssey({ apiKey: 'ody_...' });
    }

    const client = clientRef.current;
    client.connect();

    // Critical: cleanup on unmount AND HMR
    return () => {
      client.disconnect();
      clientRef.current = null;
    };
  }, []);

  return <video id="stream" />;
}
Development vs Production: These HMR patterns add complexity. Consider using environment checks to simplify your production code:
const isDev = process.env.NODE_ENV === 'development';
// Only use module-level singleton pattern in development

Finding and Closing Dangling Sessions

If you need to immediately free up your concurrent session slots, you can find and terminate processes that may have orphaned Odyssey connections.

Identify Processes with Active Connections

Odyssey sessions use WebRTC connections to our streaming servers. You can find processes holding these connections using network inspection tools.
# Find processes with connections to Odyssey servers
lsof -i | grep -E "odyssey|stun|turn" | awk '{print $1, $2}' | sort -u

# Find Node.js processes (common for SDK usage)
pgrep -l node

# Find browser processes that may have WebRTC connections
pgrep -l "Chrome|Firefox|Safari|Electron"

# Kill a specific process by PID
kill <PID>

# Force kill if unresponsive
kill -9 <PID>
You can also use Activity Monitor:
  1. Open Activity Monitor (Cmd + Space, type “Activity Monitor”)
  2. Search for “node”, “python”, or your browser name
  3. Select the process and click the X button to quit

Browser-Specific Cleanup

For web applications, dangling sessions often persist in browser tabs or service workers:
  1. Close all tabs running your Odyssey application
  2. Clear site data: Settings → Privacy → Clear browsing data → Cookies and site data
  3. Check service workers: DevTools (F12) → Application → Service Workers → Unregister
  4. Force close: chrome://restart in the address bar

Development Environment Cleanup

During development, orphaned processes are common. Here’s how to clean up:
# Kill all Node.js processes (use with caution)
pkill -f node

# Kill only processes running your specific script
pkill -f "node.*your-app-name"

# On Windows (PowerShell)
Get-Process node | Stop-Process
Using pkill or Stop-Process on broad patterns like node or python will terminate all matching processes, not just Odyssey-related ones. Use specific patterns when possible.

Monitoring Your Usage

The Developer Portal dashboard shows your current usage in real-time:
  • Concurrent Streams: The number of active interactive sessions right now
  • Total Hours Used: Cumulative streaming time this billing period
  • Simulation Hours: Time spent on simulation/headless jobs
If you believe your concurrent count is incorrect after waiting for automatic cleanup (5+ minutes), please contact support@odyssey.ml with your account details.