Melhor para: Desenvolvedores de plataforma, construtores de SaaS, qualquer implantação que atende a mais de um punhado de usuários simultâneos.
Conceitos principais
Antes de escolher um padrão, entenda três dimensões de dimensionamento:

Padrões de isolamento de sessões
Padrão 1: CLI isolada por usuário
Cada usuário obtém sua própria instância de servidor da CLI. Isolamento mais forte: as sessões, a memória e os processos de um usuário são completamente separados.

Quando usar:
- SaaS multilocatário em que o isolamento de dados é crítico
- Usuários com credenciais de autenticação diferentes
- Requisitos de conformidade (SOC 2, HIPAA)
// CLI pool manager — one CLI per user
class CLIPool {
private instances = new Map<string, { client: CopilotClient; port: number }>();
private nextPort = 5000;
async getClientForUser(userId: string, token?: string): Promise<CopilotClient> {
if (this.instances.has(userId)) {
return this.instances.get(userId)!.client;
}
const port = this.nextPort++;
// Spawn a dedicated CLI for this user
await spawnCLI(port, token);
const client = new CopilotClient({
cliUrl: `localhost:${port}`,
});
this.instances.set(userId, { client, port });
return client;
}
async releaseUser(userId: string): Promise<void> {
const instance = this.instances.get(userId);
if (instance) {
await instance.client.stop();
this.instances.delete(userId);
}
}
}
Padrão 2: CLI compartilhada com isolamento de sessão
Vários usuários compartilham um servidor da CLI, mas têm sessões isoladas por meio de IDs de sessão exclusivas. Mais leve em recursos, mas isolamento mais fraco.

Quando usar:
- Ferramentas internas com usuários confiáveis
- Ambientes restritos a recursos
- Requisitos de isolamento mais baixos
const sharedClient = new CopilotClient({
cliUrl: "localhost:4321",
});
// Enforce session isolation through naming conventions
function getSessionId(userId: string, purpose: string): string {
return `${userId}-${purpose}-${Date.now()}`;
}
// Access control: ensure users can only access their own sessions
async function resumeSessionWithAuth(
sessionId: string,
currentUserId: string
): Promise<Session> {
const [sessionUserId] = sessionId.split("-");
if (sessionUserId !== currentUserId) {
throw new Error("Access denied: session belongs to another user");
}
return sharedClient.resumeSession(sessionId);
}
Padrão 3: sessões compartilhadas (colaborativas)
Vários usuários interagem com a mesma sessão, como uma sala de chat compartilhada com o Copilot.

Quando usar:
- Ferramentas de colaboração em equipe
- Sessões de revisão de código compartilhado
- Emparelhar assistentes de programação
⚠️Importante: O SDK não fornece bloqueio de sessão interno. Você deve serializar o acesso para evitar gravações simultâneas na mesma sessão.
import Redis from "ioredis";
const redis = new Redis();
async function withSessionLock<T>(
sessionId: string,
fn: () => Promise<T>,
timeoutSec = 300
): Promise<T> {
const lockKey = `session-lock:${sessionId}`;
const lockId = crypto.randomUUID();
// Acquire lock
const acquired = await redis.set(lockKey, lockId, "NX", "EX", timeoutSec);
if (!acquired) {
throw new Error("Session is in use by another user");
}
try {
return await fn();
} finally {
// Release lock (only if we still own it)
const currentLock = await redis.get(lockKey);
if (currentLock === lockId) {
await redis.del(lockKey);
}
}
}
// Usage: serialize access to shared session
app.post("/team-chat", authMiddleware, async (req, res) => {
const result = await withSessionLock("team-project-review", async () => {
const session = await client.resumeSession("team-project-review");
return session.sendAndWait({ prompt: req.body.message });
});
res.json({ content: result?.data.content });
});
Comparação de padrões de isolamento
| CLI isolada por usuário | CLI compartilhada + Isolamento de sessão | Sessões compartilhadas | |
|---|---|---|---|
| Isolation | |||
| ✅ Concluído | |||
| ⚠️ Lógico | |||
| ❌ Compartilhado | |||
| Uso de recursos | Alta (CLI por usuário) | Baixo (uma CLI) | Baixo (uma CLI + sessão) |
| Complexidade | Medium | Baixo | Alto (bloqueio) |
| Flexibilidade de autenticação | |||
| ✅ Tokens por usuário | |||
| ⚠️ Token de serviço | |||
| ⚠️ Token de serviço | |||
| Mais adequado para | SaaS multilocatário | Ferramentas internas | Colaboração |
Escalabilidade horizontal
Vários servidores CLI por trás de um balanceador de carga

Requisito de chave: O estado da sessão deve estar no armazenamento compartilhado para que qualquer servidor da CLI possa retomar qualquer sessão.
// Route sessions to CLI servers
class CLILoadBalancer {
private servers: string[];
private currentIndex = 0;
constructor(servers: string[]) {
this.servers = servers;
}
// Round-robin selection
getNextServer(): string {
const server = this.servers[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.servers.length;
return server;
}
// Sticky sessions: same user always hits same server
getServerForUser(userId: string): string {
const hash = this.hashCode(userId);
return this.servers[hash % this.servers.length];
}
private hashCode(str: string): number {
let hash = 0;
for (let i = 0; i < str.length; i++) {
hash = (hash << 5) - hash + str.charCodeAt(i);
hash |= 0;
}
return Math.abs(hash);
}
}
const lb = new CLILoadBalancer([
"cli-1:4321",
"cli-2:4321",
"cli-3:4321",
]);
app.post("/chat", async (req, res) => {
const server = lb.getServerForUser(req.user.id);
const client = new CopilotClient({ cliUrl: server });
const session = await client.createSession({
sessionId: `user-${req.user.id}-chat`,
model: "gpt-4.1",
});
const response = await session.sendAndWait({ prompt: req.body.message });
res.json({ content: response?.data.content });
});
Sessões persistentes versus armazenamento compartilhado

Sessões persistentes são mais simples: mantêm os usuários vinculados a servidores específicos de CLI. Não é necessário armazenamento compartilhado, mas a distribuição de carga é desigual.
O armazenamento compartilhado permite que qualquer CLI manipule qualquer sessão. Melhor distribuição de carga, mas requer armazenamento em rede para ~/.copilot/session-state/.
Escalonamento vertical
Ajustando um único servidor da CLI
Um único servidor da CLI pode lidar com muitas sessões simultâneas. Principais considerações:

O gerenciamento do ciclo de vida da sessão é fundamental para o dimensionamento vertical:
// Limit concurrent active sessions
class SessionManager {
private activeSessions = new Map<string, Session>();
private maxConcurrent: number;
constructor(maxConcurrent = 50) {
this.maxConcurrent = maxConcurrent;
}
async getSession(sessionId: string): Promise<Session> {
// Return existing active session
if (this.activeSessions.has(sessionId)) {
return this.activeSessions.get(sessionId)!;
}
// Enforce concurrency limit
if (this.activeSessions.size >= this.maxConcurrent) {
await this.evictOldestSession();
}
// Create or resume
const session = await client.createSession({
sessionId,
model: "gpt-4.1",
});
this.activeSessions.set(sessionId, session);
return session;
}
private async evictOldestSession(): Promise<void> {
const [oldestId] = this.activeSessions.keys();
const session = this.activeSessions.get(oldestId)!;
// Session state is persisted automatically — safe to disconnect
await session.disconnect();
this.activeSessions.delete(oldestId);
}
}
Sessões efêmeras versus persistentes

Sessões efêmeras
Para endpoints de API sem estado, em que cada solicitação é independente:
app.post("/api/analyze", async (req, res) => {
const session = await client.createSession({
model: "gpt-4.1",
});
try {
const response = await session.sendAndWait({
prompt: req.body.prompt,
});
res.json({ result: response?.data.content });
} finally {
await session.disconnect(); // Clean up immediately
}
});
Sessões persistentes
Para interfaces de conversa ou fluxos de trabalho de execução longa:
// Create a resumable session
app.post("/api/chat/start", async (req, res) => {
const sessionId = `user-${req.user.id}-${Date.now()}`;
const session = await client.createSession({
sessionId,
model: "gpt-4.1",
infiniteSessions: {
enabled: true,
backgroundCompactionThreshold: 0.80,
},
});
res.json({ sessionId });
});
// Continue the conversation
app.post("/api/chat/message", async (req, res) => {
const session = await client.resumeSession(req.body.sessionId);
const response = await session.sendAndWait({ prompt: req.body.message });
res.json({ content: response?.data.content });
});
// Clean up when done
app.post("/api/chat/end", async (req, res) => {
await client.deleteSession(req.body.sessionId);
res.json({ success: true });
});
Implantações de contêiner
Kubernetes com armazenamento persistente
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 # See backend-services.md for how to build and push this image
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
---
apiVersion: v1
kind: Service
metadata:
name: copilot-cli
spec:
selector:
app: copilot-cli
ports:
- port: 4321
targetPort: 4321

Instâncias de Contêiner do Azure
containers:
- name: copilot-cli
image: your-registry/copilot-cli:latest # See backend-services.md for how to build and push this image
command: ["copilot", "--headless", "--host", "0.0.0.0", "--port", "4321"]
volumeMounts:
- name: session-storage
mountPath: /root/.copilot/session-state
volumes:
- name: session-storage
azureFile:
shareName: copilot-sessions
storageAccountName: myaccount
Lista de verificação de produção

| Preocupação | Recomendação |
|---|---|
| Limpeza de sessão | Execute uma limpeza periódica para excluir sessões com mais tempo do que o TTL |
| Verificações de integridade | Executar ping no servidor da CLI periodicamente; reiniciar se não responder |
| Armazenamento | Montar volumes persistentes para ~/.copilot/session-state/ |
| Segredos | Use o gerenciador de segredos da sua plataforma (Vault, K8s Secrets, etc.) |
| Monitorização | Acompanhar contagem de sessão ativa, latência de resposta, taxas de erro |
| Locking | Usar Redis ou semelhante para acesso de sessão compartilhado |
| Desligamento | Encerrar sessões ativas antes de parar os servidores de CLI |
Limitações
| Limitation | Detalhes |
|---|---|
| Nenhum bloqueio de sessão interno | Implementar o bloqueio no nível do aplicativo para acesso simultâneo |
| Nenhum balanceamento de carga interno | Usar LB externo ou malha de serviço |
| O estado da sessão é baseado em arquivo | Requer sistema de arquivos compartilhado para configurações de vários servidores |
| Tempo limite ocioso de 30 minutos | As sessões sem atividade são limpas automaticamente pela CLI |
| A CLI é de processo único | Escale adicionando mais instâncias do servidor CLI, não threads |
Próximas Etapas
- Retomada e persistência da sessão: Análise aprofundada de sessões retomáveis
- Configuração de serviços de back-end: Configuração principal do lado do servidor
- Configuração do OAuth do GitHub: Autenticação multiusuário
- BYOK (bring your own key): Usar seu próprio provedor de modelos