# \[Bug\]: Server: the thread list read blocks the event loop and every other database call for seconds on large databases · Issue \#14701 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/issues/14701)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: completed

Priority: 0

## Description

[Discussion and activity](https://git.cafe/pingdotgg/t3code/issues/14701)

---

### Before submitting

- [x] I searched existing issues and did not find a duplicate.
- [x] I included enough detail to reproduce or investigate the problem.

### Area

apps/server

### Steps to reproduce

1. Run a V2 server (`t3code/codex-turn-mapping`, or the `v0.0.45-preview.20261001.2518` build) on a large `statev2.sqlite`. Ours is 33 GB with about 3,400 threads and 250,000 turn items.
2. Let it work normally with a client connected. `getShellSnapshot` runs on every client connect and from the pull request sync sweep, roughly once a minute.
3. Watch the server's event loop while a snapshot runs, for example with a 2 ms `setInterval` that records the longest gap between ticks.

### Expected behavior

Reading the thread list does not stop the server from answering websocket pings, running other requests, or committing writes.

### Actual behavior

`ProjectionStore.getShellSnapshot` runs `selectShellThreadRows` (about 15 correlated subqueries per thread, including two `COUNT(*)` over turn items) inside `sql.withTransaction`. The SQLite client (`packages/shared/src/nodeSqliteClient.ts`) has one synchronous `node:sqlite` connection behind a one-permit semaphore on the main thread, so for the whole read:

- the event loop is blocked, and
- every other statement, including writes, waits for the lock.

On a clone of our database, the longest main-thread gap per snapshot was 1.41 to 2.24 s (12 runs). Live server traces showed the same query at 1.4 to 2.6 s about once a minute, with the stall monitor reporting 2.0 and 2.5 s stalls right after. Clients drop the connection after missing keepalives, and each reconnect fetches the snapshot again, so disconnects arrive in clusters.

### Impact

Major degradation or frequent failure

### Version or commit

`t3code/codex-turn-mapping` @ de95adc336e (also `v0.0.45-preview.20261001.2518`)

### Environment

macOS 26 (Apple Silicon), server run as a background service, 33 GB `statev2.sqlite`

### Logs or stack traces

Measured with the real `getShellSnapshot` against an APFS clone of the database, timer gap recorded with a 2 ms `setInterval`:

```
snapshot_ms  max_main_thread_gap_ms
2375         2240
1791         1677
1876         1760
1994         1884
1745         1650
1502         1411
```

