Objetivos de aprendizado
Depois de ler este artigo, você vai conseguir:
- Diferenciar 500, 502, 503 e 504 pelo sintoma exato
- Achar a causa nos logs do app e do proxy
- Corrigir as causas mais comuns e evitar que voltem
Nesta página
- O que significa cada código 5xx?
- Por que aparece um 500 Internal Server Error?
- Por que aparece um 502 Bad Gateway?
- Por que aparece um 503 Service Unavailable?
- Por que aparece um 504 Gateway Timeout?
- Como diagnosticar um erro 5xx passo a passo?
- Como evitar erros 5xx?
- Como fazer isso na Square Cloud
- Perguntas frequentes
Todo status entre 500 e 599 diz a mesma coisa: a requisição era válida, mas o servidor não conseguiu concluí-la. O visitante não fez nada de errado, e a correção está do seu lado. Os quatro códigos que você mais vai encontrar parecem iguais no navegador, mas apontam para lugares bem diferentes da cadeia da requisição.
O segredo é descobrir quem gerou o erro. Uma página crua de "500 Internal Server Error" vinda do seu framework significa que o seu código falhou. Uma página "502 Bad Gateway" simples, ou com a marca do nginx, de uma CDN ou de um load balancer, significa que o proxy na frente do app está reclamando do app.
O que significa cada código 5xx?#
| Código | Nome | Quem gera | Significado direto |
|---|---|---|---|
| 500 | Internal Server Error | O app | Uma condição inesperada impediu o app de responder |
| 502 | Bad Gateway | Um proxy ou gateway | Recebeu uma resposta inválida do servidor de origem |
| 503 | Service Unavailable | App ou proxy | Não consegue atender agora (sobrecarga ou manutenção) |
| 504 | Gateway Timeout | Um proxy ou gateway | Não recebeu resposta a tempo do servidor de origem |
As definições vêm da RFC 9110, seção 15.6. A distinção que importa: 502 e 504 só são gerados por algo que fica entre o visitante e o seu app. Sem nada na frente do app, você raramente vai vê-los, a não ser que o seu próprio código funcione como gateway para outro serviço.
Por que aparece um 500 Internal Server Error?#
O 500 é o código genérico. Seu código lançou uma exceção que ninguém tratou, e o framework respondeu com 500. O navegador não conta nada de útil; o log conta tudo.
Causas comuns, da mais à menos frequente:
- Uma exceção não tratada: ler uma propriedade de
undefined, um JSON que falhou no parse, um campo que faltou. - Uma dependência que falhou: o banco está inacessível, as credenciais estão erradas, uma API de terceiros estourou o tempo.
- Uma variável de ambiente ou arquivo de configuração que existe na sua máquina, mas não em produção.
- Falta de memória, que mata o processo no meio da requisição.
- Um deploy ruim: um módulo faltando ou um build que não terminou.
Para diagnosticar, reproduza a requisição e leia o stack trace nos logs do app. Depois garanta que os erros sejam capturados e registrados, em vez de vazarem para o visitante:
import express from "express";
const app = express();
app.get("/users/:id", async (req, res) => {
const user = await findUser(req.params.id); // pode lançar erro
if (!user) return res.status(404).json({ error: "not found" });
res.json(user);
});
// O Express 5 encaminha para cá as promises rejeitadas dos handlers async
app.use((err, req, res, next) => {
console.error(`${req.method} ${req.url}`, err);
res.status(500).json({ error: "internal error" });
});
app.listen(process.env.PORT ?? 3000, "0.0.0.0");Repare no 404 para usuário inexistente. Devolver 500 num caso normal de "não encontrado" lota os logs e esconde as falhas de verdade.
Por que aparece um 502 Bad Gateway?#
Um 502 significa que o proxy foi até o seu app e recebeu lixo, ou nada. Como diz a MDN, um servidor atuando como gateway recebeu uma resposta inválida do servidor de origem. Na prática, o app quase sempre está fora do ar ou inacessível. Confira nesta ordem:
- O app quebrou ou não está rodando. O proxy não tem com quem falar. Olhe o processo: ele encerrou, entrou em loop de reinícios ou foi morto por falta de memória?
- O app ainda está subindo. Logo depois de um deploy ou restart, a porta ainda não abriu. Inicializações lentas (migrações, carregar modelos grandes) aumentam essa janela.
- Porta ou endereço errado. O proxy encaminha para a porta 3000, mas o app escuta na 8080. Ou o app escuta em
127.0.0.1dentro de um container, e nada de fora consegue alcançá-lo. Escute em0.0.0.0e leia a porta do ambiente. - O app fechou a conexão no meio da resposta, por exemplo com um crash durante a requisição ou um keep-alive mais curto que o do proxy.
- Uma regra do proxy aponta para a origem errada, como um erro de digitação no
proxy_passou um endereço de backend desatualizado.
Se o app funciona quando você abre a porta dele diretamente, mas falha atrás do proxy, o problema está na configuração do proxy, não no código. Veja o que um proxy reverso faz para entender esse salto.
Por que aparece um 503 Service Unavailable?#
Um 503 diz "agora não". Segundo a RFC 9110, o servidor está temporariamente incapaz de atender a requisição por sobrecarga ou manutenção programada, e pode mandar um cabeçalho Retry-After dizendo quando tentar de novo (seção 10.2.3).
Causas típicas:
- Todos os workers ou vagas de conexão estão ocupados, então as requisições novas são recusadas ou estouram a fila.
- Não sobrou nenhum backend saudável: um load balancer marcou todos como reprovados no health check.
- Um modo de manutenção proposital.
- Um rate limiter ou um serviço de origem descartando carga.
Se você devolve 503 de propósito, diga quando tentar de novo, para que robôs de busca e clientes esperem antes de repetir:
app.use((req, res, next) => {
if (process.env.MAINTENANCE === "1") {
res.set("Retry-After", "600"); // segundos
return res.status(503).send("Voltamos em cerca de 10 minutos");
}
next();
});Para resolver sobrecarga de verdade, ache o gargalo primeiro: CPU no máximo, memória cheia, uma consulta lenta segurando todas as conexões. Adicionar workers não ajuda se o limite é o banco de dados.
Por que aparece um 504 Gateway Timeout?#
Um 504 significa que o proxy conectou ao seu app, mas o app demorou demais para responder. O app está vivo, só que lento. O nginx, por exemplo, espera por padrão 60 segundos entre duas leituras seguidas da origem (proxy_read_timeout 60s), segundo a documentação do módulo proxy do nginx. Outros proxies e CDNs têm limites próprios, muitas vezes menores ou fixos.
Causas típicas:
- Uma consulta lenta no banco, um índice faltando ou um lock.
- Uma requisição que chama outra API que trava, sem timeout seu.
- Trabalho pesado feito dentro da requisição: processar imagem, gerar relatório, exportações grandes.
- Um app saturado, em que as requisições esperam numa fila antes de serem atendidas.
A correção quase nunca é "aumentar o timeout do proxy". Tire o trabalho longo de dentro da requisição, responda rápido com o id de uma tarefa e deixe o cliente consultar o status ou receber um webhook. Coloque timeouts explícitos em toda chamada de saída, para que uma dependência travada falhe rápido com um erro claro. Se uma rota precisa mesmo de um limite maior, aumente só para ela. Para entender a camada que distribui as requisições entre instâncias e também pode cortá-las, veja o que é um load balancer.
Como diagnosticar um erro 5xx passo a passo?#
- Descubra quem respondeu. Confira os cabeçalhos da resposta e o corpo da página. Um cabeçalho
Serverou uma página de erro com a marca de uma CDN mostra qual camada falhou. - Leia os logs do app no horário do erro. Um stack trace significa 500. Nenhum trace e nenhuma requisição registrada significa que o proxy nem chegou ao app. O guia como ler os logs da aplicação ajuda nessa etapa.
- Confira o processo. Está rodando, há quanto tempo está no ar, reiniciou há pouco, quanta memória usa?
- Chame o app diretamente, sem passar pelo proxy, com
curl -i http://localhost:3000/health. Se funcionar, olhe a configuração do proxy. - Confira as dependências. Banco, cache e APIs externas. Uma dependência lenta ou morta gera 500, 503 e 504 do mesmo jeito.
- Observe o padrão. Uma rota só aponta para um bug no código. Todas as rotas apontam para um app ou proxy fora do ar. Erros intermitentes sob carga apontam para capacidade ou timeouts.
Um endpoint /health que verifica o banco e devolve 200 ou 503 economiza tempo aqui, e load balancers podem usá-lo para tirar uma instância com falha do rodízio. Para uma lista mais ampla quando o site inteiro fica inacessível, veja por que meu site caiu.
Como evitar erros 5xx?#
- Registre todo erro não tratado com o caminho da requisição e um id de requisição.
- Defina timeouts em toda chamada de banco e HTTP que o app faz.
- Reinicie o processo automaticamente se ele encerrar, e crie um alerta para quedas repetidas.
- Faça teste de carga antes do lançamento para descobrir onde a capacidade acaba.
- Rode migrações e tarefas lentas de inicialização antes de o app aceitar tráfego, não durante.
- Acompanhe a proporção de respostas 5xx ao longo do tempo. Uma linha subindo avisa antes de os usuários reclamarem.
Como fazer isso na Square Cloud#
Na Square Cloud, cada aplicação web roda no próprio container isolado, e a investigação de um 5xx começa do mesmo jeito: pelos logs. Eles aparecem em tempo real no painel, na CLI, na extensão do VS Code e no app de celular, o que facilita pegar um crash ou um stack trace logo depois que uma requisição falha.
Um 502 depois do deploy costuma significar que o app não escuta em 0.0.0.0 na porta da variável PORT, então confira isso primeiro. Os containers ficam sempre ligados, sem cold start nem modo de suspensão, e o reinício automático (ligado por padrão no deploy pelo painel) traz de volta a aplicação que encerra com erro. Estouro de memória é diferente: a aplicação para e fica parada até você aumentar a RAM nas configurações e iniciá-la de novo. Aplicações web precisam de no mínimo 512 MB de RAM.
Para ver com que frequência os erros acontecem, o analytics web incluso em todo plano mostra rotas e status codes, coletados no servidor. Os planos Pro e Enterprise acrescentam latência p50, p95 e p99 e logs HTTP, úteis para achar as rotas lentas por trás dos 504. Seu site também ganha um subdomínio *.squareweb.app com HTTPS, então você pode testar o app diretamente antes de ligar um domínio personalizado.
Os recursos de hospedagem de sites estão na página de Sites.
Hospedagem de sites
Sites estáticos e SSR com TLS automático e CDN global
Perguntas frequentes
Qual a diferença entre o erro 502 e o 504?
Um 502 significa que o proxy recebeu uma resposta inválida (ou nenhuma, porque a conexão foi recusada ou caiu). Um 504 significa que o proxy conectou, mas o app não respondeu a tempo.
Erro 5xx é culpa minha ou do visitante?
A classe 5xx indica que o servidor não conseguiu atender uma requisição válida, então a causa está do lado do servidor. Recarregar a página, limpar cookies ou trocar de navegador raramente resolve.
Erro 503 prejudica o SEO?
Uma queda curta costuma fazer pouco estrago: o Google desacelera o rastreamento quando vê erros 5xx e mantém por um tempo as URLs já indexadas. URLs que continuam devolvendo erro de servidor acabam saindo do índice.
Por que aparece um 502 logo depois do deploy?
Normalmente o app quebrou ao iniciar, ainda está subindo ou escuta em uma porta ou endereço diferente do que o proxy espera. Os logs do app mostram qual dos três.
Mais em Sites
Ver todos os 20 artigos- O que é um site estático e onde hospedarSite estático é um conjunto de arquivos HTML, CSS e JavaScript prontos, entregues iguais a todos os visitantes. Veja como funciona, quando usar e onde hospedar.
- Quanto custa hospedar um site?Hospedar um site custa de zero a algumas dezenas de dólares por mês. Veja o que entra na conta: hospedagem, domínio, tráfego e extras, com exemplos e limites.
- Quanto custa hospedar um site estáticoHospedar um site estático custa de zero a algumas dezenas de dólares por mês na maioria dos casos. Veja como o tráfego define o preço, com a conta passo a passo.
- Quanto custa hospedar um app Next.jsHospedar um app Next.js custa de zero, com export estático, a dezenas de dólares por mês com servidor. Veja como cada modelo cobra e os custos escondidos.