---
title: Per-session update isolation (cheaper updates with many sessions open)
---

# Per-session update isolation

## What it is

**What it is:** an opt-in performance mode that makes each live update cheaper when many sessions
are streaming at once. Normally, every time any session emits a token, Omniscio re-runs a handful
of small per-session lookups for **every** open session panel — even the ones that didn't change.
With this on, each mounted panel reads its per-session state through **one** consolidated lookup
instead of five, so a busy agent's output nudges far less work across all your open panels. The app
looks and behaves exactly the same; only the internal per-update cost drops.

**Where:** Settings → Performance → **"Per-session update isolation"**. Default **OFF** (opt-in).
Flipping it takes effect immediately — no restart. It never changes what your sessions actually do;
turning it off returns to the previous behavior exactly.

## Where to find it

**Settings → Performance → Per-session update isolation.** It is off by default; flipping it takes effect immediately, with no restart.

## How it behaves

### Why it exists

This is the residual per-update cost that remains after the adaptive-hidden-window throttle (which
cut how *often* background sessions commit). This cuts how *expensive* each commit is: a store
update re-runs every subscriber's selector, so with ~13–30 mounted keep-alive panels each holding
~5 separate per-session subscriptions, a single streaming token re-ran ~150 small selectors.
Consolidating each panel's five reads into one cuts that to ~30 — a deterministic **~80% fewer
per-commit selector executions** at 30 panels (measured in
`tests/unit/stores/select-session-panel-subscriptions.test.ts`, which also proves the consolidated
read wakes a panel on exactly the same updates the five separate reads did — no stale panel, no
missed update).

### How it works

- A mounted session panel reads five per-session slices in its body: the pending action, the
  pending permission, the auth-retry state, the subagent state, and the per-session usage. Each is
  its own store subscription that re-runs on every commit.
- When the toggle is ON, those five reads are served by one canonical `selectSessionPanelSubscriptions`
  selector wrapped in `useShallow`, so the panel runs one selector per commit instead of five. Because
  shallow-equality over the five fields is exactly "did any of them change for this session", the panel
  re-renders on the same updates as before — the behavior is identical, there's just one subscriber.
- The OFF↔ON choice is a component swap in `SessionPanelImpl` (the same shape the **Fast session
  switching** toggle uses): flipping the setting live-remounts the panel body onto the other path.

### Kill switches

- The Settings toggle itself (`perSessionSubscriptionIsolation`, default `false`).
- `AMC_DISABLE_PER_SESSION_SUB_ISOLATION=1` env var — force-OFF regardless of the setting (it can
  never force the mode ON). Reverts to the five separate subscriptions byte-for-byte.

### Scope

- This isolates a panel's **component-level** per-session subscriptions. The conversation-cache /
  streaming reads that live deeper in the panel's hooks are not part of this pass (a larger,
  higher-churn change left for later).
- Works the same on desktop and the mobile web embed; it's a rendering-cost change, not a UI change.

## Related

- [perf-control.md](perf-control.md) — the screen that shows what is being paced on this machine, and why.

### Related

- Contract (invariants + locking tests):
  `.claude/memory/contracts/store-subscription-isolation-contract.md`
- The switch-render half of the same perf story: [isolated-session-view.md](isolated-session-view.md),
  [inbox-prerender.md](inbox-prerender.md)

