---
sidebar_position: 9
title: Executor availability WebSocket
description: Receive a snapshot and live updates for executors rentable on Lium.
---

> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lium.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Executor availability WebSocket

Use this public WebSocket to maintain a current list of executors that are rentable right now. It replaces repeated polling of `GET /executors` for availability changes.

Connect to:

```text
wss://lium.io/api/executors/ws
```

The endpoint requires no API key. The server sends JSON text frames only; clients do not send messages.

## Keep a local executor map

The first frame on every connection is always a complete `snapshot`. Replace local state with it. Then apply each `upsert` or `delete` by `executor_id`.

```ts
const executors = new Map<string, ExecutorAvailability>()
const socket = new WebSocket('wss://lium.io/api/executors/ws')

socket.onmessage = ({ data }) => {
  const frame = JSON.parse(data)

  switch (frame.type) {
    case 'snapshot':
      executors.clear()
      for (const executor of frame.executors) executors.set(executor.id, executor)
      break
    case 'upsert':
      executors.set(frame.executor_id, frame.executor)
      break
    case 'delete':
      executors.delete(frame.executor_id)
      break
    case 'heartbeat':
      break
  }
}
```

## Frames

Every frame has these envelope fields:

| Field | Meaning |
| --- | --- |
| `type` | `snapshot`, `upsert`, `delete`, or `heartbeat` |
| `schema_version` | Protocol version. The current version is `1`. |
| `seq` | Monotonic sequence number within this WebSocket connection. |
| `ts` | Server publish time as Unix seconds. |

### Snapshot

```json
{
  "type": "snapshot",
  "schema_version": 1,
  "seq": 42,
  "ts": 1787572800.5,
  "executors": [
    {
      "id": "ad83de56-8a04-4ab1-ac5a-4ab007b4e2b3",
      "machine_name": "NVIDIA H200",
      "price_per_gpu": 2.5,
      "gpu_count": 8,
      "available_gpu_count": 8,
      "uptime_in_minutes": 4815,
      "specs": { "gpu": { "count": 8, "details": [] } }
    }
  ]
}
```

### Upsert and delete

An `upsert` adds an executor to the rentable set or replaces its full availability projection. Its `executor` object is the same projection the snapshot carries; the examples on this page show a few of its fields, not all of them. A `delete` means it is no longer rentable; the server does not expose the reason.

```json
{
  "type": "upsert",
  "schema_version": 1,
  "seq": 43,
  "ts": 1787572801.0,
  "executor_id": "ad83de56-8a04-4ab1-ac5a-4ab007b4e2b3",
  "executor": { "id": "ad83de56-8a04-4ab1-ac5a-4ab007b4e2b3", "available_gpu_count": 4 }
}
```

```json
{
  "type": "delete",
  "schema_version": 1,
  "seq": 44,
  "ts": 1787572802.0,
  "executor_id": "ad83de56-8a04-4ab1-ac5a-4ab007b4e2b3"
}
```

`heartbeat` has only the envelope and confirms that the connection is still live.

## Reconnects and compatibility

There is no resume token. On every reconnect, discard any partial state when the next `snapshot` arrives and start applying subsequent frames from that snapshot. A later `snapshot` on an existing connection also replaces the full local state.

The server closes with WebSocket code `1013` when it is not ready, the connection limit is reached, or a slow client has fallen behind. Retry with exponential backoff.

Treat `schema_version` as a contract: reconnecting cannot make a client compatible with a higher version. Add support for the new version before accepting it.

The `executor` object is an availability projection. It intentionally excludes internal details and most high-churn telemetry; only use fields present in a received frame. `uptime_in_minutes` is included for marketplace filtering and sorting, but its minute-by-minute change does not trigger an `upsert` by itself.
