Skip to content

fix(opencode): evict idle per-directory instances to bound serve memory#33713

Open
Evgen1000end wants to merge 1 commit into
anomalyco:devfrom
Evgen1000end:fix/instance-eviction
Open

fix(opencode): evict idle per-directory instances to bound serve memory#33713
Evgen1000end wants to merge 1 commit into
anomalyco:devfrom
Evgen1000end:fix/instance-eviction

Conversation

@Evgen1000end

@Evgen1000end Evgen1000end commented Jun 24, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #33720
Related to #33213

Type of change

  • Bug fix

What does this PR do?

serve caches one InstanceStore entry per directory (x-opencode-directory) and never frees it — no TTL/LRU/idle eviction. A server that sees many distinct directories (e.g. one directory per session) accumulates an instance each, with its own file watchers, LSP/MCP subprocesses, plugins and bus subscriptions, so RSS climbs until OOM.

Adds opt-in eviction:

  • entries track lastUsed + an active in-flight counter;
  • a sweeper disposes idle entries (active==0) older than OPENCODE_INSTANCE_IDLE_TTL_MS, and/or trims LRU ones above OPENCODE_INSTANCE_MAX;
  • the request middleware acquires/releases (via ensuring), so an in-flight request is never evicted mid-turn;
  • eviction frees only runtime resources — the session lives in the DB and re-loads on the next request.

With neither env var set the sweeper never starts; behavior is unchanged.

How did you verify your code works?

  • Unit tests (test/project/instance-eviction.test.ts): an idle instance is evicted after the TTL; an acquired one is not until released. Existing instance tests pass and bun typecheck is clean.
  • Mock OpenAI-compatible provider (no real LLM), 60 sequential sessions, one directory each, ~1s apart, RSS sampled from /proc: off -> 506->1338 MB and climbing, 0 disposed; on (TTL 4s, max 4) -> ~700 MB flat, 59/60 disposed.
  • Evicted a session's instance, then re-prompted that session — it re-booted and continued with full history.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

serve cached one InstanceStore entry per directory (x-opencode-directory) and
never freed it, so a server seeing many distinct directories (e.g. one per
session) accumulated an instance each — file watchers, LSP/MCP subprocesses,
plugins and bus subscriptions — until OOM.

Adds opt-in idle-TTL + LRU eviction with an in-flight pin so a busy instance is
never evicted mid-turn. Disposing only frees runtime resources; the session is
in the DB and re-loads on the next request. Default behavior is unchanged when
the env vars are unset.

Related to anomalyco#33213
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@rastvorus

Copy link
Copy Markdown

The problem is relevant. Very necessary for our development

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Server mode: InstanceStore never evicts per-directory instances (unbounded memory)

2 participants