### Summary On a machine running many concurrent `opencode` sessions, `opencode.db` grew to **73 GB in about 8 days**. **64.4 GB of that is the `event` table alone.** The actual conversation data is tiny by comparison: `part` is 2.1 GB and `message` is 1.7 GB. Essentially all of the growth is the event log. ### Environment - opencode 1.18.25 - macOS - Database at the default path, `~/.local/share/opencode/opencode.db`, journal mode WAL - Around 43 concurrent `opencode` processes sharing the one database (heavy automation, not a typical single-user setup) ### Numbers | table | size | | --- | --- | | `event` | 64.4 GB | | `part` | 2.1 GB | | `message` | 1.7 GB | `event` held **2,594,731 rows**. Sampling the 200,000 most recent: | type | count | share | | --- | --- | --- | | `message.part.updated.1` | 126,747 | 63.4% | | `message.updated.1` | 57,558 | 28.8% | | `session.updated.1` | 15,607 | 7.8% | | `session.created.1` | 88 | 0.04% | So roughly 92% of rows are per-chunk streaming progress events. A row's `data` payload is typically around 1 KB. Growth measured at roughly **8 GB/day** under this load. ### Symptoms, in the order they appeared 1. New sessions fail to start. The server process launches and binds its port correctly, and `/global/health` answers, but `POST /session` times out. From the outside this looks like a port or networking fault, which sent us down the wrong path for a while. 2. A second, later variant: a session is created successfully, then the process becomes unresponsive before consuming its first message. 3. The database becomes too slow to introspect. A simple `SELECT type, count(*) FROM event GROUP BY type` exceeded 120 seconds and had to be abandoned. 4. Disk pressure. At 8 GB/day this is the dominant consumer of free space on the machine. Notably this is **not** CPU load related. We saw the same failure at load average 29 and at load average 4.6. ### What appears to be missing - **No retention.** The `event` table looks append-only with no TTL, cap or rotation. - **No maintenance command.** `opencode db` exposes only an interactive shell and `path`. There is no `prune`, `compact` or `vacuum`. - **No configuration option.** Nothing in the config appears to control event retention. The only remedy available to us was to stop everything and delete the database, losing all session history. `VACUUM` was not practical: it needs roughly the database's own size in free space, and takes an exclusive lock across every attached process. ### Suggested fixes, roughly in order of preference 1. **Do not persist per-chunk streaming deltas at all, or coalesce them.** `message.part.updated` appears to be a live progress notification. The final state is already durable in `part`. If these events exist to drive in-flight subscribers, they may not need to outlive the turn that produced them. This alone would remove the large majority of the growth. 2. **Add a retention policy with a sane default**, for example keep events for N days or cap the table at N rows, pruned on startup or on a timer, and make it configurable. 3. **Add `opencode db prune` and `opencode db compact`** so operators have a supported way to recover without deleting the whole database and losing history. 4. **Fail loudly rather than hanging.** A `POST /session` timeout gives no hint that the cause is database size. A startup warning above some threshold, or a clear error, would have saved us several hours of misdiagnosis. ### Why it matters beyond our setup We hit this quickly because of concurrency, but the growth is driven by tokens streamed rather than by sessions created. Any long-running heavy user should reach the same place eventually, just more slowly, and the first symptom they see will be "cannot create a session" with no indication why. Happy to provide more detail on the row distribution or timings if useful.