Cloud & Infraestrutura • Nathan Geeksman • 08/04/2026

HAProxy na Prática: Balanceamento de Carga sem Mistério

Num sistema que precisa aguentar tráfego real, ter um único servidor respondendo a tudo é uma escolha que funciona até um certo ponto — e esse ponto chega mais cedo do que o esperado. Balanceamento de carga é a resposta para isso: em vez de um servidor tentando absorver tudo, um intermediário distribui as requisições entre várias instâncias, de forma que nenhuma delas seja sobrecarregada e o sistema inteiro continue respondendo mesmo que uma peça falhe.

O HAProxy é há anos uma das soluções mais usadas para isso. É open source, extremamente rápido, maduro e com uma documentação densa. Também é conhecido por uma configuração que intimida na primeira leitura — mas a estrutura é mais simples do que parece.

A lógica por trás da configuração

Um arquivo de configuração do HAProxy gira em torno de dois conceitos centrais: frontend e backend.

O frontend é o ponto de entrada — define em qual porta o HAProxy vai escutar e quais regras de roteamento aplicar antes de encaminhar a requisição. O backend é o grupo de servidores que vai de fato processar essa requisição. Entre os dois, o HAProxy decide quem recebe o quê, com base no algoritmo de balanceamento configurado.

Uma configuração funcional mínima se parece com isso:

global
    log stdout format raw local0
    maxconn 50000

defaults
    mode http
    timeout connect 5s
    timeout client  30s
    timeout server  30s
    option redispatch
    retries 3

frontend http_in
    bind *:80
    default_backend servidores_app

backend servidores_app
    balance roundrobin
    option httpchk GET /health HTTP/1.1\r\nHost:\ localhost
    http-check expect status 200

    server app01 10.0.0.1:8080 check inter 3s rise 2 fall 3
    server app02 10.0.0.2:8080 check inter 3s rise 2 fall 3
    server app03 10.0.0.3:8080 check inter 3s rise 2 fall 3

Vale entender o que cada parâmetro do server está fazendo: check ativa a verificação de saúde periódica; inter 3s define o intervalo entre checks; rise 2 significa que o servidor precisa passar em 2 checks consecutivos para ser considerado saudável depois de uma falha; fall 3 significa que 3 falhas consecutivas o marcam como indisponível. Esses valores têm impacto direto em quanto tempo o HAProxy leva para perceber que um servidor caiu — e quanto tempo leva para confiar nele novamente.

Algoritmos de balanceamento

roundrobin é o padrão e o mais simples: cada servidor recebe requisições em sequência, em rotação. Funciona bem quando os servidores são homogêneos e as requisições têm duração similar.

Mas nem sempre é a escolha certa. Algumas alternativas importantes:

leastconn — encaminha para o servidor com menos conexões ativas no momento. Ideal para requisições de longa duração, como websockets ou uploads grandes, onde roundrobin acabaria concentrando carga desproporcional em alguns servidores.

source — usa o IP de origem para determinar sempre qual servidor vai receber a requisição de um cliente específico. Útil quando a aplicação não tem sessão compartilhada entre instâncias e você precisa que um mesmo usuário sempre chegue no mesmo servidor.

uri — roteia com base na URI da requisição. Usado em cenários de cache, onde você quer que a mesma URL sempre chegue no mesmo servidor para maximizar o hit de cache.

backend api_servers
    balance leastconn
    # resto da configuração...

Health checks que realmente funcionam

O check padrão do HAProxy verifica apenas se consegue abrir uma conexão TCP com o servidor. Isso não é suficiente: um servidor pode aceitar conexões e ainda assim estar completamente travado internamente.

O caminho correto é verificar um endpoint HTTP real que exercite a aplicação — idealmente um que cheque dependências críticas como banco de dados:

backend servidores_app
    option httpchk GET /health HTTP/1.1\r\nHost:\ localhost
    http-check expect status 200
    # ou, para checar uma string específica no body:
    # http-check expect string "healthy"

    server app01 10.0.0.1:8080 check inter 3s rise 2 fall 3

O endpoint /health da aplicação deve retornar 200 apenas quando tudo estiver funcionando. Se o banco estiver inacessível, ele deve retornar 500 — e o HAProxy vai remover esse servidor do pool automaticamente.

TLS e terminação SSL

Em produção, o tráfego externo deve ser HTTPS. O HAProxy pode fazer a terminação TLS — recebe HTTPS do cliente, faz a comunicação interna com os backends em HTTP simples:

frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/exemplo.pem
    redirect scheme https if !{ ssl_fc }

    # Boas práticas de segurança TLS
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11

    default_backend servidores_app

O arquivo .pem precisa conter o certificado e a chave privada concatenados. Se estiver usando Let's Encrypt, o Certbot gera os arquivos separados — é necessário concatená-los: cat fullchain.pem privkey.pem > /etc/haproxy/certs/exemplo.pem.

Observabilidade

O HAProxy expõe uma página de estatísticas que dá uma visão instantânea do estado de cada backend e servidor:

frontend stats
    bind *:8404
    stats enable
    stats uri /stats
    stats refresh 10s
    stats auth admin:senha_segura

Para ambientes com Prometheus, existe o haproxy_exporter que converte essas métricas para o formato que o Prometheus entende, permitindo dashboards no Grafana com latência por backend, taxa de erros, conexões ativas e estado de cada servidor.

As métricas mais importantes para acompanhar: haproxy_backend_http_responses_total (separada por código de status), haproxy_backend_response_time_average_seconds e haproxy_server_status (0 = down, 1 = up).

O que costuma dar errado

Timeouts mal calibrados são responsáveis por boa parte dos problemas difíceis de diagnosticar. O timeout server precisa ser maior do que o tempo máximo que qualquer requisição legítima pode levar. Se uma operação pesada leva 25 segundos e o timeout está em 30s, você está operando sem margem — e usuários vão ver erros esporádicos que parecem aleatórios.

Health check no endpoint errado também é comum. Verificar / ou uma rota que só retorna HTML estático não diz nada sobre o estado real da aplicação. O endpoint de health deve ser dedicado e expressivo.

Ausência de option redispatch significa que se um servidor cair no meio de uma requisição e não havia persistência de sessão, o cliente recebe um erro em vez de ser redirecionado automaticamente para outro servidor saudável.

A documentação oficial do HAProxy é densa mas bem organizada — para qualquer parâmetro que apareça numa configuração real, ela é a referência definitiva. Para quem usa Kubernetes, vale explorar também o ingress-nginx e o HAProxy Kubernetes Ingress Controller como alternativas nativamente integradas ao ecossistema de contêineres.