{"meta":{"title":"Escalabilidade e multitenância","intro":"Projete sua implantação do SDK Copilot para atender a vários usuários, manipular sessões simultâneas e dimensionar horizontalmente em toda a infraestrutura. Este guia aborda padrões de isolamento de sessão, topologias de dimensionamento e práticas recomendadas de produção.","product":"GitHub Copilot","breadcrumbs":[{"href":"/pt/enterprise-cloud@latest/copilot","title":"GitHub Copilot"},{"href":"/pt/enterprise-cloud@latest/copilot/how-tos","title":"Instruções"},{"href":"/pt/enterprise-cloud@latest/copilot/how-tos/copilot-sdk","title":"SDK do Copilot"},{"href":"/pt/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup","title":"Configurar o SDK do Copilot"},{"href":"/pt/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup/scaling","title":"Scaling"}],"documentType":"article"},"body":"# Escalabilidade e multitenância\n\nProjete sua implantação do SDK Copilot para atender a vários usuários, manipular sessões simultâneas e dimensionar horizontalmente em toda a infraestrutura. Este guia aborda padrões de isolamento de sessão, topologias de dimensionamento e práticas recomendadas de produção.\n\n<!-- markdownlint-disable GHD046 GHD005 -->\n\n<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->\n\nPara opções e padrões no nível do SDK, consulte [Multilocação e implantações de servidores](/pt/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup/multi-tenancy).\n\n**Melhor para:** Desenvolvedores de plataforma, construtores de SaaS, qualquer implantação que atende a mais de um punhado de usuários simultâneos.\n\n## Conceitos principais\n\nAntes de escolher um padrão, entenda três dimensões de dimensionamento:\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-0.png)\n\n## Padrões de isolamento de sessões\n\n### Padrão 1: CLI isolada por usuário\n\nCada 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.\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-1.png)\n\n**Quando usar:**\n\n* SaaS multilocatário em que o isolamento de dados é crítico\n* Usuários com credenciais de autenticação diferentes\n* Requisitos de conformidade (SOC 2, HIPAA)\n\n```typescript\n// CLI pool manager — one CLI per user\nclass CLIPool {\n    private instances = new Map<string, { client: CopilotClient; port: number }>();\n    private nextPort = 5000;\n\n    async getClientForUser(userId: string, token?: string): Promise<CopilotClient> {\n        if (this.instances.has(userId)) {\n            return this.instances.get(userId)!.client;\n        }\n\n        const port = this.nextPort++;\n\n        // Spawn a dedicated CLI for this user\n        await spawnCLI(port, token);\n\n        const client = new CopilotClient({\n            cliUrl: `localhost:${port}`,\n        });\n\n        this.instances.set(userId, { client, port });\n        return client;\n    }\n\n    async releaseUser(userId: string): Promise<void> {\n        const instance = this.instances.get(userId);\n        if (instance) {\n            await instance.client.stop();\n            this.instances.delete(userId);\n        }\n    }\n}\n```\n\n### Padrão 2: CLI compartilhada com isolamento de sessão\n\nVá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.\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-2.png)\n\n**Quando usar:**\n\n* Ferramentas internas com usuários confiáveis\n* Ambientes restritos a recursos\n* Requisitos de isolamento mais baixos\n\n```typescript\nconst sharedClient = new CopilotClient({\n    cliUrl: \"localhost:4321\",\n});\n\n// Enforce session isolation through naming conventions\nfunction getSessionId(userId: string, purpose: string): string {\n    return `${userId}-${purpose}-${Date.now()}`;\n}\n\n// Access control: ensure users can only access their own sessions\nasync function resumeSessionWithAuth(\n    sessionId: string,\n    currentUserId: string\n): Promise<Session> {\n    const [sessionUserId] = sessionId.split(\"-\");\n    if (sessionUserId !== currentUserId) {\n        throw new Error(\"Access denied: session belongs to another user\");\n    }\n    return sharedClient.resumeSession(sessionId);\n}\n```\n\n### Padrão 3: sessões compartilhadas (colaborativas)\n\nVários usuários interagem com a mesma sessão, como uma sala de chat compartilhada com o Copilot.\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-3.png)\n\n**Quando usar:**\n\n* Ferramentas de colaboração em equipe\n* Sessões de revisão de código compartilhado\n* Assistentes de programação em par\n\n> ⚠️**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.\n\n```typescript\nimport Redis from \"ioredis\";\n\nconst redis = new Redis();\n\nasync function withSessionLock<T>(\n    sessionId: string,\n    fn: () => Promise<T>,\n    timeoutSec = 300\n): Promise<T> {\n    const lockKey = `session-lock:${sessionId}`;\n    const lockId = crypto.randomUUID();\n\n    // Acquire lock\n    const acquired = await redis.set(lockKey, lockId, \"NX\", \"EX\", timeoutSec);\n    if (!acquired) {\n        throw new Error(\"Session is in use by another user\");\n    }\n\n    try {\n        return await fn();\n    } finally {\n        // Release lock (only if we still own it)\n        const currentLock = await redis.get(lockKey);\n        if (currentLock === lockId) {\n            await redis.del(lockKey);\n        }\n    }\n}\n\n// Usage: serialize access to shared session\napp.post(\"/team-chat\", authMiddleware, async (req, res) => {\n    const result = await withSessionLock(\"team-project-review\", async () => {\n        const session = await client.resumeSession(\"team-project-review\");\n        return session.sendAndWait({ prompt: req.body.message });\n    });\n\n    res.json({ content: result?.data.content });\n});\n```\n\n## Comparação de padrões de isolamento\n\n|                                   | CLI isolada por usuário | CLI compartilhada + Isolamento de sessão | Sessões compartilhadas   |\n| --------------------------------- | ----------------------- | ---------------------------------------- | ------------------------ |\n| **Isolation**                     |                         |                                          |                          |\n| ✅ Concluído                       |                         |                                          |                          |\n| ⚠️ Lógico                         |                         |                                          |                          |\n| ❌ Compartilhado                   |                         |                                          |                          |\n| **Uso de recursos**               | Alta (CLI por usuário)  | Baixo (uma CLI)                          | Baixo (uma CLI + sessão) |\n| **Complexidade**                  | Medium                  | Baixo                                    | Alto (bloqueio)          |\n| **Flexibilidade de autenticação** |                         |                                          |                          |\n| ✅ Tokens por usuário              |                         |                                          |                          |\n| ⚠️ Token de serviço               |                         |                                          |                          |\n| ⚠️ Token de serviço               |                         |                                          |                          |\n| **Mais adequado para**            | SaaS multilocatário     | Ferramentas internas                     | Colaboração              |\n\n## Escalabilidade horizontal\n\n### Vários servidores CLI por trás de um balanceador de carga\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-4.png)\n\n**Requisito de chave:** O estado da sessão deve estar no **armazenamento compartilhado** para que qualquer servidor da CLI possa retomar qualquer sessão.\n\n```typescript\n// Route sessions to CLI servers\nclass CLILoadBalancer {\n    private servers: string[];\n    private currentIndex = 0;\n\n    constructor(servers: string[]) {\n        this.servers = servers;\n    }\n\n    // Round-robin selection\n    getNextServer(): string {\n        const server = this.servers[this.currentIndex];\n        this.currentIndex = (this.currentIndex + 1) % this.servers.length;\n        return server;\n    }\n\n    // Sticky sessions: same user always hits same server\n    getServerForUser(userId: string): string {\n        const hash = this.hashCode(userId);\n        return this.servers[hash % this.servers.length];\n    }\n\n    private hashCode(str: string): number {\n        let hash = 0;\n        for (let i = 0; i < str.length; i++) {\n            hash = (hash << 5) - hash + str.charCodeAt(i);\n            hash |= 0;\n        }\n        return Math.abs(hash);\n    }\n}\n\nconst lb = new CLILoadBalancer([\n    \"cli-1:4321\",\n    \"cli-2:4321\",\n    \"cli-3:4321\",\n]);\n\napp.post(\"/chat\", async (req, res) => {\n    const server = lb.getServerForUser(req.user.id);\n    const client = new CopilotClient({ cliUrl: server });\n\n    const session = await client.createSession({\n        sessionId: `user-${req.user.id}-chat`,\n        model: \"gpt-5.4\",\n    });\n\n    const response = await session.sendAndWait({ prompt: req.body.message });\n    res.json({ content: response?.data.content });\n});\n```\n\n### Sessões persistentes versus armazenamento compartilhado\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-5.png)\n\n**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.\n\n**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/`.\n\n## Escalonamento vertical\n\n### Ajustando um único servidor da CLI\n\nUm único servidor da CLI pode lidar com muitas sessões simultâneas. Principais considerações:\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-6.png)\n\n**O gerenciamento do ciclo de vida** da sessão é fundamental para o dimensionamento vertical:\n\n```typescript\n// Limit concurrent active sessions\nclass SessionManager {\n    private activeSessions = new Map<string, Session>();\n    private maxConcurrent: number;\n\n    constructor(maxConcurrent = 50) {\n        this.maxConcurrent = maxConcurrent;\n    }\n\n    async getSession(sessionId: string): Promise<Session> {\n        // Return existing active session\n        if (this.activeSessions.has(sessionId)) {\n            return this.activeSessions.get(sessionId)!;\n        }\n\n        // Enforce concurrency limit\n        if (this.activeSessions.size >= this.maxConcurrent) {\n            await this.evictOldestSession();\n        }\n\n        // Create or resume\n        const session = await client.createSession({\n            sessionId,\n            model: \"gpt-5.4\",\n        });\n\n        this.activeSessions.set(sessionId, session);\n        return session;\n    }\n\n    private async evictOldestSession(): Promise<void> {\n        const [oldestId] = this.activeSessions.keys();\n        const session = this.activeSessions.get(oldestId)!;\n        // Session state is persisted automatically — safe to disconnect\n        await session.disconnect();\n        this.activeSessions.delete(oldestId);\n    }\n}\n```\n\n## Sessões efêmeras versus persistentes\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-7.png)\n\n### Sessões efêmeras\n\nPara endpoints de API sem estado, em que cada solicitação é independente:\n\n```typescript\napp.post(\"/api/analyze\", async (req, res) => {\n    const session = await client.createSession({\n        model: \"gpt-5.4\",\n    });\n\n    try {\n        const response = await session.sendAndWait({\n            prompt: req.body.prompt,\n        });\n        res.json({ result: response?.data.content });\n    } finally {\n        await session.disconnect();  // Clean up immediately\n    }\n});\n```\n\n### Sessões persistentes\n\nPara interfaces de conversa ou fluxos de trabalho de execução longa:\n\n```typescript\n// Create a resumable session\napp.post(\"/api/chat/start\", async (req, res) => {\n    const sessionId = `user-${req.user.id}-${Date.now()}`;\n\n    const session = await client.createSession({\n        sessionId,\n        model: \"gpt-5.4\",\n        infiniteSessions: {\n            enabled: true,\n            backgroundCompactionThreshold: 0.80,\n        },\n    });\n\n    res.json({ sessionId });\n});\n\n// Continue the conversation\napp.post(\"/api/chat/message\", async (req, res) => {\n    const session = await client.resumeSession(req.body.sessionId);\n    const response = await session.sendAndWait({ prompt: req.body.message });\n\n    res.json({ content: response?.data.content });\n});\n\n// Clean up when done\napp.post(\"/api/chat/end\", async (req, res) => {\n    await client.deleteSession(req.body.sessionId);\n    res.json({ success: true });\n});\n```\n\n## Implantações de contêiner\n\n### Kubernetes com armazenamento persistente\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: copilot-cli\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: copilot-cli\n  template:\n    metadata:\n      labels:\n        app: copilot-cli\n    spec:\n      containers:\n        - name: copilot-cli\n          image: your-registry/copilot-cli:latest  # See backend-services.md for how to build and push this image\n          args: [\"--headless\", \"--host\", \"0.0.0.0\", \"--port\", \"4321\"]\n          env:\n            - name: COPILOT_GITHUB_TOKEN\n              valueFrom:\n                secretKeyRef:\n                  name: copilot-secrets\n                  key: github-token\n          ports:\n            - containerPort: 4321\n          volumeMounts:\n            - name: session-state\n              mountPath: /root/.copilot/session-state\n      volumes:\n        - name: session-state\n          persistentVolumeClaim:\n            claimName: copilot-sessions-pvc\n---\napiVersion: v1\nkind: Service\nmetadata:\n  name: copilot-cli\nspec:\n  selector:\n    app: copilot-cli\n  ports:\n    - port: 4321\n      targetPort: 4321\n```\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-8.png)\n\n### Instâncias de Contêiner do Azure\n\n```yaml\ncontainers:\n  - name: copilot-cli\n    image: your-registry/copilot-cli:latest  # See backend-services.md for how to build and push this image\n    command: [\"copilot\", \"--headless\", \"--host\", \"0.0.0.0\", \"--port\", \"4321\"]\n    volumeMounts:\n      - name: session-storage\n        mountPath: /root/.copilot/session-state\n\nvolumes:\n  - name: session-storage\n    azureFile:\n      shareName: copilot-sessions\n      storageAccountName: myaccount\n```\n\n## Lista de verificação de produção\n\n![Diagrama: Fluxograma mostrando o processo descrito.](/assets/images/help/copilot/copilot-sdk/setup-scaling-diagram-9.png)\n\n| Preocupação                     | Recomendação                                                                   |\n| ------------------------------- | ------------------------------------------------------------------------------ |\n| **Limpeza de sessão**           | Execute uma limpeza periódica para excluir sessões com mais tempo do que o TTL |\n| **Verificações de integridade** | Executar ping no servidor da CLI periodicamente; reiniciar se não responder    |\n| Armazenamento                   | Montar volumes persistentes para `~/.copilot/session-state/`                   |\n| **Segredos**                    | Use o gerenciador de segredos da sua plataforma (Vault, K8s Secrets, etc.)     |\n| **Monitorização**               | Acompanhar contagem de sessão ativa, latência de resposta, taxas de erro       |\n| **Locking**                     | Usar Redis ou semelhante para acesso de sessão compartilhado                   |\n| **Desligamento**                | Encerrar sessões ativas antes de parar os servidores de CLI                    |\n\n## Limitações\n\n| Limitation                                  | Detalhes                                                                         |\n| ------------------------------------------- | -------------------------------------------------------------------------------- |\n| **Nenhum bloqueio de sessão interno**       | Implementar o bloqueio no nível do aplicativo para acesso simultâneo             |\n| **Nenhum balanceamento de carga interno**   | Usar LB externo ou malha de serviço                                              |\n| **O estado da sessão é baseado em arquivo** | Requer sistema de arquivos compartilhado para configurações de vários servidores |\n| **Tempo limite ocioso de 30 minutos**       | As sessões sem atividade são limpas automaticamente pela CLI                     |\n| **A CLI é de processo único**               | Escale adicionando mais instâncias do servidor CLI, não threads                  |\n\n## Próximas Etapas \n\n* **[Retomada e persistência da sessão](/pt/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/features/session-persistence)**: Análise aprofundada de sessões retomáveis\n* **[Configuração de serviços de back-end](/pt/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup/backend-services)**: Configuração principal do lado do servidor\n* **[Configuração do OAuth do GitHub](/pt/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/setup/github-oauth)**: Autenticação multiusuário\n* **[BYOK (Bring Your Own Key - traga sua própria chave)](/pt/enterprise-cloud@latest/copilot/how-tos/copilot-sdk/auth/byok)**: Usar seu próprio provedor de modelos"}