# Como evitar estado global no servidor de vez

> Published 2026-10-11T02:09:17.645Z on https://www.crazystack.com.br/pt/p/como-evitar-estado-global-no-servidor-de-vez/
> Source video: https://www.youtube.com/watch?v=5vKcNaWXtCY

Estado global no servidor faz uma requisição contaminar outra: variáveis compartilhadas, caches e objetos instanciados fora de escopo alteram resultados conforme a ordem e a concorrência das chamadas. A solução passa por funções autocontidas, request context e injeção de dependência.

## Por que requisições HTTP devem ser stateless

Requisições HTTP são independentes por design, e o protocolo foi definido assim desde a especificação [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html), publicada em 2022 como consolidação das regras originais. Cada requisição precisa carregar tudo o que o servidor precisa para executar a ação, incluindo a identificação de quem chama.

Na prática, isso significa que o servidor não lembra de você entre uma chamada e outra. Quando você navega no YouTube e clica em outro vídeo, cada requisição carrega um identificador, como um token ou cookie, provando que você é você. O servidor nunca assume que o "usuário atual" persiste em memória.

Guardar algo como `currentUser = "galego"` em uma variável do servidor quebra esse contrato. As requisições chegam em paralelo, e cada usuário precisa receber as recomendações dele, não as do último que fez login.

## Onde o estado global aparece sem você notar

Estado global no servidor não é só a variável óbvia do usuário atual. Ele se esconde em lugares que parecem inofensivos, e reconhecer esses pontos é metade da solução.

### Cache em memória

Instanciar um cache dentro do processo do servidor é o exemplo mais comum. Ferramentas como o [Redis](https://redis.io), um banco de dados em memória muito usado para cache, podem rodar embutidas, e um simples `Map` em JavaScript já cumpre o mesmo papel. Tudo que qualquer requisição escrever ali afeta todas as outras.

### Módulos que viram singletons

Em JavaScript, uma variável no topo do arquivo, como `port = 3000`, se comporta como global: o módulo é um singleton e o valor é compartilhado pelo sistema inteiro. Se alguma requisição alterar essa variável, altera para todos.

### Objetos compartilhados entre métodos

Uma instância de moeda ou de desconto criada fora da classe, ou em uma classe compartilhada, carrega o mesmo risco. Configurações exportadas de módulos também entram nessa conta: são estado global que qualquer parte do código pode mutar.

## Side effects criam bugs que você não reproduz

Uma função confiável recebe tudo de que precisa como parâmetro e não altera nada fora dela. Quando ela depende de um desconto instanciado externamente e ainda por cima muta esse valor, ela viola as duas regras ao mesmo tempo: a entrada vem de fora e o efeito colateral vaza para o servidor.

O resultado é que `calculatePrice(30)` deixa de ter resposta determinística. O retorno depende do valor do desconto naquele instante, definido por outra requisição. Quando o bug estourar em produção, chamar a função com os mesmos parâmetros na sua máquina não reproduz nada, porque o estado externo não veio junto no log.

O cenário típico é pior do que parece. O erro só acontece quando o usuário é do tipo retail e o produto tem estoque zero, condições que moram no banco de dados. Sem logar esse contexto, você olha uma chamada com valor 30 e não tem como saber por que falhou. Esse é o custo real do estado global: reprodutibilidade destruída.

Não por acaso, linguagens como Python e TypeScript têm incorporado cada vez mais estilo funcional, que valoriza funções puras e sem efeitos colaterais. O paradigma existe exatamente para eliminar essa classe de problema.

## Race conditions: o risco mais óbvio do estado compartilhado

Duas requisições paralelas lendo e escrevendo o mesmo estado criam race conditions. É a consequência mais direta do estado global no servidor e a mais fácil de explicar: se o request A altera o desconto enquanto o request B calcula o preço, o resultado de B depende de uma corrida que ninguém controla.

A mesma lógica vale para funções que acumulam valores em um subtotal externo em vez de receber a lista como parâmetro e reduzir sobre ela. O subtotal vira terreno disputado por todas as chamadas concorrentes, e cada requisição contamina a seguinte.

## Soluções: estado local, request context e injeção de dependência

Existem três caminhos complementares para eliminar a contaminação entre requisições, e eles funcionam juntos.

### Passe o estado explicitamente

Quando a função precisa do usuário, busque-o no banco e passe o objeto como parâmetro na chamada. Uma função puramente de código, com o mesmo input, deve retornar o mesmo output. Se o bug acontecer, você reconstrói o objeto de usuário e reproduz o problema. A única exceção honesta é o que toca banco de dados ou API externa, porque isso sempre interage com algo fora do seu controle.

### Use request context

Muitos frameworks e code bases adotam o padrão de contexto de requisição: cada request agrupa seu próprio contexto, que você repassa para frente. Na hora de logar, debugar e reproduzir, entender o que aconteceu fica muito mais simples.

### Injete as dependências

Um provedor de pagamento instanciado fora da função parece inofensivo, mas é estado externo invisível. Com injeção de dependência, você define uma interface e injeta o provedor ao construir a classe de checkout. Mesmo sem o contexto completo dentro da função, o estado da classe registra qual provedor estava ativo naquele momento.

Frameworks de request-response como [Express](https://expressjs.com) no Node.js e [FastAPI](https://fastapi.tiangolo.com) em Python induzem exatamente esse comportamento: ao seguir o tutorial, você dificilmente compartilha contexto entre requisições. O framework não garante que você não vai errar, mas torna o erro bem menos provável.

## Quando estado global no servidor é aceitável

Nem todo estado global é vilão. Uma constante de porta, como `port = 3000`, que ninguém altera em runtime, não causa problema real. O mesmo vale para um limite como `maxUploadSize = 10 GB`: se o valor nunca muda depois de definido, o risco de contaminação simplesmente não existe.

Configurações exportadas de módulos também costumam ser aceitáveis, desde que sejam somente leitura na prática. O único perigo é outro ponto do código mutar esses valores; se isso acontecer no seu time, uma alternativa é carregar a configuração uma única vez no boot do servidor e transformá-la em um objeto read-only. É defesa extra, e na maioria dos projetos não é necessária.

## Perguntas frequentes sobre estado global

- **O que é estado global no servidor?** É qualquer dado compartilhado por todas as requisições do processo: variáveis de módulo, caches em memória, objetos instanciados fora de escopo e configurações mutáveis. Se um request altera o valor, todos os demais enxergam a mudança.

- **Por que estado global causa bugs difíceis de reproduzir?** Porque o resultado de uma função passa a depender do estado externo no momento da chamada, e não apenas dos parâmetros. Sem logar esse estado, chamar a função com os mesmos inputs localmente não reproduz o erro de produção.

- **Cache em memória é sempre estado global ruim?** Não. Cache é útil, mas é compartilhado por definição. O problema aparece quando requisições escrevem nele valores que afetam a lógica de outras requisições, ou quando a ordem de escrita altera resultados.

- **Frameworks modernos resolvem isso sozinhos?** Eles induzem o caminho certo: Express, FastAPI e similares entregam um contexto por requisição e desencorajam compartilhamento. Mas nada impede você de criar variáveis globais no seu código por cima do framework.

- **Injeção de dependência elimina o estado externo?** Ela o torna visível e controlável. A dependência continua existindo, mas fica registrada no construtor da classe, então você consegue saber qual implementação estava ativa quando o bug ocorreu.

## Do vídeo ao artigo: transforme suas explicações em conteúdo

A ideia central aqui é que bugs sutis nascem de contexto invisível: o que a função não mostra nos parâmetros é justamente o que impede você de reproduzir o erro. Esse tipo de insight costuma ficar preso em vídeos longos, como as aulas do canal do Augusto Galego, e muito do que você explica ao vivo merecia uma versão escrita, pesquisável e bem estruturada.

Se você ensina programação, system design ou qualquer tema técnico em vídeo, o [Skala Blog](https://skalablog.com) transforma essa gravação em artigo: você cola a URL do YouTube, o conteúdo é transcrito e vira um texto organizado, pronto para revisar e publicar.

Materiais como o curso de system design do [Crazystack](https://crazystack.com.br) mostram como o mesmo assunto rende formatos diferentes — aula em vídeo para quem acompanha, artigo para quem busca a resposta pontual. Cabe a você escolher onde cada explicação vive.

[Source video](https://www.youtube.com/watch?v=5vKcNaWXtCY)
