How to Configure Kubernetes Deployments with Persistent Session Storage for Copilot SDK

Mount a shared PersistentVolumeClaim at /root/.copilot/session-state and use explicit sessionId values when creating sessions to enable state persistence across pod restarts and horizontal scaling.

The Copilot SDK persists session state on the local filesystem under ~/.copilot/session-state/ according to the official documentation in docs/features/session-persistence.md. In Kubernetes environments, this data is ephemeral by default and disappears when pods restart or migrate. Configuring persistent session storage ensures that long-running AI coding sessions survive container crashes, node drains, and scaling events.

Understanding Session Persistence Requirements

The SDK only persists sessions that have an explicit sessionId defined. Without a custom ID, the CLI treats sessions as transient and does not write checkpoint data to disk. Additionally, when running multiple CLI replicas behind a load balancer, the storage backend must support concurrent access from multiple pods to allow any replica to resume any session.

Key configuration requirements include:

  • Shared storage: Use a ReadWriteMany PersistentVolume for horizontal scaling scenarios
  • Explicit session IDs: Required for the SDK to trigger persistence logic
  • Mount path: Must align with the SDK default at /root/.copilot/session-state
  • Cleanup policies: Optional idle timeout configuration via CopilotClientOptions

Step 1: Create a Shared PersistentVolumeClaim

For multi-pod deployments, define a PersistentVolumeClaim that supports concurrent access. According to docs/setup/scaling.md, this enables the horizontal scaling pattern where any pod can serve any session.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: copilot-sessions-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: standard

Use ReadWriteMany access mode when running multiple CLI replicas. For single-pod deployments, ReadWriteOnce is sufficient, but prevents horizontal scaling.

Step 2: Mount the Volume in Your Deployment

Configure the Deployment to mount the PVC at the SDK's default session state location. The Copilot CLI requires write access to /root/.copilot/session-state to create checkpoint files.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: copilot-cli
spec:
  replicas: 3
  selector:
    matchLabels:
      app: copilot-cli
  template:
    metadata:
      labels:
        app: copilot-cli
    spec:
      containers:
        - name: copilot-cli
          image: your-registry/copilot-cli:latest
          args: ["--headless", "--host", "0.0.0.0", "--port", "4321"]
          env:
            - name: COPILOT_GITHUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: copilot-secrets
                  key: github-token
          ports:
            - containerPort: 4321
          volumeMounts:
            - name: session-state
              mountPath: /root/.copilot/session-state
      volumes:
        - name: session-state
          persistentVolumeClaim:
            claimName: copilot-sessions-pvc

Expose the CLI via a Kubernetes Service to enable internal cluster communication:

apiVersion: v1
kind: Service
metadata:
  name: copilot-cli
spec:
  selector:
    app: copilot-cli
  ports:
    - port: 4321
      targetPort: 4321

Step 3: Implement Explicit Session IDs

As documented in docs/features/session-persistence.md, you must provide a custom sessionId when calling createSession(). The SDK only writes state to disk for sessions with explicit identifiers.

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient({
  cliUrl: "http://copilot-cli:4321",
});

// Create a resumable session with a deterministic ID
const session = await client.createSession({
  sessionId: `user-${userId}-task-${Date.now()}`,
  model: "gpt-5.2-codex",
});

// Perform work
await session.sendAndWait({ prompt: "Analyze repository files" });

// Disconnect keeps state on disk
await session.disconnect();

Step 4: Configure Automatic Cleanup (Optional)

Prevent storage exhaustion by configuring idle timeouts via CopilotClientOptions.sessionIdleTimeoutSeconds. This setting triggers automatic cleanup of inactive session files as described in the Automatic cleanup section of docs/features/session-persistence.md.

const client = new CopilotClient({
  cliUrl: "http://copilot-cli:4321",
  sessionIdleTimeoutSeconds: 30 * 60, // 30 minutes
});

Resuming Sessions Across Pod Restarts

With persistent storage mounted, any pod in the deployment can resume sessions created by previous instances. Use the resumeSession() method with the original session ID:

// Resume from any pod in the cluster
const resumed = await client.resumeSession("user-42-task-1706932800");
await resumed.sendAndWait({ prompt: "Continue where we left off" });

This capability fulfills the horizontal scaling requirements outlined in docs/setup/scaling.md, allowing load balancers to route follow-up requests to any available replica.

Key Source Files Reference

Summary

  • Mount location: Configure PVCs at /root/.copilot/session-state to match the SDK default
  • Access mode: Use ReadWriteMany for horizontal scaling; ReadWriteOnce works only for single-pod deployments
  • Session IDs: Always provide explicit sessionId values to createSession()—the SDK only persists named sessions
  • Resumption: Use resumeSession() with the original ID to restore state after pod restarts
  • Cleanup: Configure sessionIdleTimeoutSeconds to automatically remove stale session files

Frequently Asked Questions

Why does the Copilot SDK require explicit session IDs for persistence?

The SDK treats sessions without custom IDs as transient to prevent disk pollution from temporary connections. According to docs/features/session-persistence.md, only sessions created with an explicit sessionId parameter trigger the persistence mechanism that writes checkpoint data to ~/.copilot/session-state/.

What storage access mode should I use for multi-pod deployments?

Use ReadWriteMany (RWX) access mode for the PersistentVolumeClaim. As documented in docs/setup/scaling.md, this allows multiple pods to simultaneously read and write session data, enabling any replica to resume any session. ReadWriteOnce restricts access to a single node and prevents horizontal scaling.

Can I run the Copilot CLI in Kubernetes without persistent storage?

Yes, but sessions will be lost when pods restart or migrate. Without a mounted PVC at /root/.copilot/session-state, the SDK stores checkpoints on the container's ephemeral filesystem, which is destroyed when containers stop. Use persistent storage for production workloads requiring session continuity.

How do I configure session timeouts to prevent storage exhaustion?

Set the sessionIdleTimeoutSeconds option in CopilotClientOptions when initializing the client. This parameter defines how long the SDK retains inactive session files before automatic deletion, as implemented in the automatic cleanup logic described in docs/features/session-persistence.md.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →