Implantação zero-downtime de serviços TypeScript: guia passo a passo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Como atualizar um serviço sem acordar os usuários?



Imagine: sexta-feira, à noite, você decide aplicar rapidamente uma correção de bug na produção. Você clica em deploy — e seu mensageiro, streaming de cinema ou CRM fica fora do ar por 30 segundos. Milhares de usuários veem um 502 Bad Gateway nesse momento. E se for um gateway de pagamento? Calcule os prejuízos.



A implantação zero-downtime (implantação com tempo de inatividade zero) não é um luxo, mas um padrão para serviços TypeScript modernos. Neste artigo, vamos abordar técnicas reais usadas em produção: desde graceful shutdown até implantação azul-verde e rolling update. Você terá padrões prontos para aplicar em TypeScript.



Por que a implantação comum de uma aplicação TypeScript é perigosa?



Quando você executa npm run build && node dist/index.js, vários problemas ocorrem:



  • Quebra de conexões — o processo antigo é encerrado enquanto novas requisições ainda estão chegando.
  • Perda de dados na memória — sessões não salvas, cache, filas.
  • Inicialização suja — o novo processo não teve tempo de aquecer, mas já está recebendo tráfego.


No TypeScript (Node.js), a assincronicidade agrava a situação: você não sabe quais promises ainda estão sendo executadas. Mas existe solução.



Técnica #1: Graceful Shutdown (encerramento gracioso)



A base do zero-downtime é o tratamento correto dos sinais do SO. Quando o orquestrador (Kubernetes, PM2) decide parar seu serviço, ele envia SIGTERM. Seu código deve parar de aceitar novas requisições, aguardar a conclusão das atuais e só então ser encerrado.



Implementação em TypeScript com Express



import express, { Request, Response } from 'express';import http from 'http';

const app = express();let server: http.Server;

app.get('/health', (req: Request, res: Response) => { res.status(200).json({ status: 'ok' });});

// Sinal do Docker/K8sprocess.on('SIGTERM', async () => { console.log('SIGTERM recebido, iniciando graceful shutdown...'); // 1. Para de ouvir novas conexões server.close(() => { console.log('Servidor HTTP fechado'); // 2. Fecha conexões com banco de dados, Redis, etc. // await db.disconnect(); process.exit(0); });

// 3. Dá tempo para as requisições atuais (timeout de 30 seg) setTimeout(() => { console.error('Encerramento forçado por timeout'); process.exit(1); }, 30000);});

const PORT = process.env.PORT || 3000;server = app.listen(PORT, () => { console.log(`Serviço iniciado na porta ${PORT}`);});


Importante: em TypeScript, use http.Server do módulo http, não o tipo Express. O método server.close() lida corretamente com conexões keep-alive.



Técnica #2: Rolling Update (atualização gradual)



Se você tem várias réplicas do serviço (3-5 instâncias em execução), o rolling update as atualiza uma por uma. Enquanto uma é reiniciada, as outras recebem o tráfego.



Exemplo para Kubernetes Deployment



# deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata:  name: my-typescript-servicespec:  replicas: 3  strategy:    type: RollingUpdate    rollingUpdate:      maxUnavailable: 1      # quantos pods podem ficar indisponíveis      maxSurge: 1            # quantos novos pods podem ser criados além do plano  template:    spec:      containers:      - name: app        image: myregistry/service:v2        ports:        - containerPort: 3000        livenessProbe:          httpGet:            path: /health            port: 3000          initialDelaySeconds: 5          periodSeconds: 10        readinessProbe:          httpGet:            path: /ready            port: 3000          initialDelaySeconds: 3          periodSeconds: 5


Adicione ao seu aplicativo TypeScript o endpoint /ready, que retorna 200 apenas quando o serviço

Blogs

Book Recommendations