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
ReadWriteManyPersistentVolume 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
docs/features/session-persistence.md: Defines session persistence semantics, requiredsessionIdusage, and cleanup policiesdocs/setup/scaling.md: Documents horizontal scaling patterns and shared storage requirements for multi-pod deploymentsdocs/setup/backend-services.md: Provides configuration details for running the CLI as a backend service, includingcliUrlsetup
Summary
- Mount location: Configure PVCs at
/root/.copilot/session-stateto match the SDK default - Access mode: Use
ReadWriteManyfor horizontal scaling;ReadWriteOnceworks only for single-pod deployments - Session IDs: Always provide explicit
sessionIdvalues tocreateSession()—the SDK only persists named sessions - Resumption: Use
resumeSession()with the original ID to restore state after pod restarts - Cleanup: Configure
sessionIdleTimeoutSecondsto 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →