# How jcode Handles Memory Isolation Between Concurrent Sessions

> jcode ensures memory isolation between concurrent sessions using UUID-scoped directories and exclusive in-process caches. Discover how jcode prevents shared mutable state between sessions.

- Repository: [Jeremy Huang/jcode](https://github.com/1jehuang/jcode)
- Tags: internals
- Published: 2026-04-30

---

**jcode ensures memory isolation between concurrent sessions by using UUID-scoped on-disk directories and exclusive in-process caches owned by each Session instance, with no shared mutable state between sessions.**

The `jcode` repository implements a robust concurrency model that guarantees strict memory isolation between concurrent sessions through filesystem separation and strict ownership patterns. This article examines the Rust source code to explain exactly how the system prevents cross-session data leakage while maintaining high performance.

## Per-Session On-Disk Storage Architecture

### UUID-Based Session Identification

When a new session initializes, `jcode` generates a unique identifier via `new_memorable_session_id` and creates a dedicated directory for that session's persistent data. This design ensures that each session operates within its own filesystem sandbox, with separate storage for journals, snapshots, and environment data.

### Path Isolation via Storage Helpers

The path helpers defined in [`src/storage_paths.rs`](https://github.com/1jehuang/jcode/blob/main/src/storage_paths.rs) enforce this isolation by requiring a session ID for all file operations. Functions like `session_journal_path` and `session_path` construct paths that incorporate the session UUID, making it impossible for one session to resolve another session's file paths. Because these helpers always take a session ID as an argument, two sessions can never read or write each other's files.

## Isolated In-Process Memory Caches

### The Session Struct Design

Each `Session` instance maintains its own `SessionMemoryProfileCache` and dirty flag, explicitly excluded from serialization to prevent accidental persistence:

```rust
pub struct Session {
    …
    #[serde(skip)]
    memory_profile_cache: SessionMemoryProfileCache,
    #[serde(skip)]
    memory_profile_dirty: bool,
    …}

```

*(see [`src/session.rs`](https://github.com/1jehuang/jcode/blob/main/src/session.rs) lines 30-38)*

### Cache Lifetime and Ownership

These fields are **not** shared across `Session` objects; they live only for the lifetime of that specific `Session` value. The `#[serde(skip)]` attribute prevents the cache from being written to disk, ensuring that in-memory data structures never outlive their owning session or leak into other instances.

## Server-Side Concurrency Model

### SessionControlHandle Architecture

The server maintains isolation through `SessionControlHandle` structures defined in [`src/server/state.rs`](https://github.com/1jehuang/jcode/blob/main/src/server/state.rs). Each active session maps to a handle containing an `Arc<Mutex<Session>>`:

```rust
pub struct SessionControlHandle {
    pub id: String,
    pub session: Arc<Mutex<Session>>,
    …
}

```

### Task Isolation

When processing concurrent requests, the server looks up the handle by session ID in a `HashMap<String, SessionControlHandle>`, clones the associated `Session`, and executes turn logic within its own async task. Because each `Session` clone includes independent caches and the journal file remains exclusively open for that session, no mutable state spans across concurrent tasks.

## UI Layer Session References

Higher-level components in [`src/tui/workspace_client.rs`](https://github.com/1jehuang/jcode/blob/main/src/tui/workspace_client.rs) reference sessions only by their IDs. Functions such as `queue_resume_session` manipulate workspace maps without accessing other sessions' memory caches:

```rust
pub fn queue_resume_session(session_id: String) {
    state.pending_resume_session = Some(session_id);
}

```

*(see [`src/tui/workspace_client.rs`](https://github.com/1jehuang/jcode/blob/main/src/tui/workspace_client.rs) lines 106-108)*

This ID-only reference pattern ensures that UI operations cannot accidentally traverse into another session's isolated memory space.

## Practical Implementation Examples

Creating isolated sessions and running them concurrently:

```rust
// Create a new session – a fresh UUID is assigned and a new folder is allocated.
let sess = Session::new()?;               // generates a unique `id`
sess.persist_state.save()?;               // writes only to this session’s files

// Run two sessions concurrently – each gets its own lock and cache.
let handle_a = server.state.get_handle("session_a")?;
let handle_b = server.state.get_handle("session_b")?;

tokio::join!(
    run_turn(handle_a.clone()),
    run_turn(handle_b.clone()),
);

```

Modifying session-specific memory profiles:

```rust
// The memory profile cache lives only inside the Session struct.
fn add_memory_stats(sess: &mut Session, block_id: &str, stats: ContentBlockMemoryStats) {
    sess.memory_profile_cache.insert(block_id.to_owned(), stats);
    sess.memory_profile_dirty = true;
}

```

## Key Source Files

The isolation mechanism spans these critical components:

- [`src/session.rs`](https://github.com/1jehuang/jcode/blob/main/src/session.rs) – Defines the `Session` struct with its per-session memory cache
- [`src/server/state.rs`](https://github.com/1jehuang/jcode/blob/main/src/server/state.rs) – Holds `SessionControlHandle`, the per-session concurrency primitive
- [`src/storage_paths.rs`](https://github.com/1jehuang/jcode/blob/main/src/storage_paths.rs) – Generates file-system paths scoped by session ID
- [`src/tui/workspace_client.rs`](https://github.com/1jehuang/jcode/blob/main/src/tui/workspace_client.rs) – UI layer referencing sessions only by ID
- [`src/session/memory_profile.rs`](https://github.com/1jehuang/jcode/blob/main/src/session/memory_profile.rs) – Implementation of `SessionMemoryProfileCache`

## Summary

- `jcode` generates unique UUID-based session IDs via `new_memorable_session_id` to create isolated on-disk directories
- Path helpers in [`src/storage_paths.rs`](https://github.com/1jehuang/jcode/blob/main/src/storage_paths.rs) ensure sessions cannot resolve each other's file paths by requiring session ID parameters
- Each `Session` owns exclusive `SessionMemoryProfileCache` and `memory_profile_dirty` fields marked with `#[serde(skip)]` to prevent cross-session persistence
- The server uses `SessionControlHandle` with `Arc<Mutex<Session>>` to isolate concurrent async tasks, with each session operating on its own cloned data
- UI components reference sessions only by ID, preventing accidental cache traversal between sessions

## Frequently Asked Questions

### How does jcode prevent sessions from accessing each other's files?

`jcode` enforces filesystem isolation through UUID-based directory structures and path helper functions in [`src/storage_paths.rs`](https://github.com/1jehuang/jcode/blob/main/src/storage_paths.rs). Methods like `session_journal_path` and `session_path` always incorporate the session ID into the file path, ensuring that path resolution is scoped to the requesting session's exclusive directory.

### What happens to session memory caches when a session ends?

The `SessionMemoryProfileCache` lives only within the `Session` struct instance and is marked with `#[serde(skip)]` to exclude it from serialization. When the `Session` value drops out of scope, the cache is automatically deallocated, leaving no residual data in memory or on disk.

### Is jcode's session isolation thread-safe for concurrent requests?

Yes, the server implementation in [`src/server/state.rs`](https://github.com/1jehuang/jcode/blob/main/src/server/state.rs) uses `Arc<Mutex<Session>>` within `SessionControlHandle` structures. Each concurrent request operates on its own locked `Session` clone, ensuring that mutable state never overlaps between simultaneous tasks executing on different sessions.

### How does the server manage multiple active sessions simultaneously?

The server maintains a `HashMap<String, SessionControlHandle>` keyed by session ID. When a request arrives, the server looks up the handle by ID and spawns an async task with the cloned session data, ensuring that each active session operates within its own isolated execution context.