From Wave 5 — N-05 and R-06. Severity: medium (architecture) / low (measured perf cost ~0.9 µs/msg).
Code
`kalshi/ws/client.py:144-179` (`_recv_loop`):
```python
data = json.loads(raw) # line 147 — parse 1
...
if msg_type in ("orderbook_snapshot", "orderbook_delta"):
snapshot = OrderbookSnapshotMessage.model_validate(data) # line 171
...
await self._dispatcher.dispatch(raw) # line 179 — passes raw, not data
```
`kalshi/ws/dispatch.py:70-71`:
```python
data = json.loads(raw) # parse 2
```
For orderbook frames the dispatcher also re-validates via `model_cls.model_validate(data)` at `dispatch.py:92`. So every orderbook frame is JSON-parsed twice and Pydantic-validated twice.
Cost
Measured ~0.9 µs/message for the duplicate `json.loads` (R-06). At 10k msg/s that's ~0.9% of a CPU. Orderbook re-validation cost is comparable (~3 µs). Real on busy streams.
Fix options
- (a) Move sequence-tracking + orderbook-state update inside `MessageDispatcher.dispatch` so each frame is parsed and validated once. Cleaner separation of concerns.
- (b) Change `dispatch` signature to accept the pre-parsed `dict` from the recv loop. Smaller refactor, keeps responsibilities split.
Either way, the duplication is a maintenance hazard — two parsers can drift.
From Wave 5 — N-05 and R-06. Severity: medium (architecture) / low (measured perf cost ~0.9 µs/msg).
Code
`kalshi/ws/client.py:144-179` (`_recv_loop`):
```python
data = json.loads(raw) # line 147 — parse 1
...
if msg_type in ("orderbook_snapshot", "orderbook_delta"):
snapshot = OrderbookSnapshotMessage.model_validate(data) # line 171
...
await self._dispatcher.dispatch(raw) # line 179 — passes raw, not data
```
`kalshi/ws/dispatch.py:70-71`:
```python
data = json.loads(raw) # parse 2
```
For orderbook frames the dispatcher also re-validates via `model_cls.model_validate(data)` at `dispatch.py:92`. So every orderbook frame is JSON-parsed twice and Pydantic-validated twice.
Cost
Measured ~0.9 µs/message for the duplicate `json.loads` (R-06). At 10k msg/s that's ~0.9% of a CPU. Orderbook re-validation cost is comparable (~3 µs). Real on busy streams.
Fix options
Either way, the duplication is a maintenance hazard — two parsers can drift.