Tags: FastCGI · Nginx · Caddy · Traefik · Reverse Proxy · HTTP/3 · PHP-FPM · Performance

Por Duarte Spínola · 4 de Julho de 2026

FastCGI e Reverse Proxies: Nginx vs Caddy vs Traefik em 2026

O FastCGI tem 30 anos mas continua a ser o protocolo mais eficiente para comunicar entre web servers e aplicações backend (PHP, Python, Ruby). Os reverse proxies modernos — Nginx, Caddy e Traefik — usam diferentes abordagens para terminar TLS, encaminhar tráfego e servir aplicações. Este guia compara os três, com configurações práticas e benchmarks reais, inspirado na análise técnica de agwa.name.

Para complementar, consulta os artigos sobre Caddy Reverse Proxy HTTPS, Traefik Ingress Kubernetes, Cloudflare Tunnel Zero Trust e Postfix SMTP Relay.

Conteúdos

1. FastCGI: 30 Anos e Ainda Melhor que HTTP

O FastCGI foi introduzido em 1996 pela Open Market como evolução do CGI tradicional. Em vez de lançar um processo novo por pedido (CGI), o FastCGI mantém processos persistentes que recebem múltiplos pedidos por um socket. Trinta anos depois, continua a ser o protocolo mais eficiente para comunicar com aplicações backend.

Vantagens do FastCGI sobre HTTP como protocolo de proxy:

  • Binário, não texto — cabeçalhos em pares nome/valor, sem parsing de HTTP
  • Menos overhead — sem headers HTTP completos no pedido interno
  • Multiplexação — múltiplos pedidos num só socket (FastCGI suporta streams)
  • Sem buffering — streaming directo, sem limite de tamanho de body
  • Timeouts granulares — separate read timeout, write timeout, connect timeout

💡 Dica: Quando o reverse proxy fala FastCGI directamente com a aplicação (em vez de HTTP), evita uma camada completa de parsing HTTP. Para WordPress/PHP, isto significa ~15-20% menos overhead por pedido.

2. O Problema do HTTP como Proxy Backend

Quando um reverse proxy usa HTTP para comunicar com o backend, há problemas:

  • Duplicação de headers — o proxy adiciona X-Forwarded-For, X-Real-IP, Host, etc., que o backend tem de interpretar
  • Buffering obrigatório — muitos proxies fazem buffer do body completo antes de encaminhar
  • Timeouts confusos — o timeout HTTP do proxy não distingue connect, read, write
  • Limites de tamanho — client_max_body_size, proxy_request_buffering
  • Conexões TCP extras — cada pedido cria uma nova conexão TCP (ou usa keepalive pool)

Com FastCGI, o proxy e o backend partilham um socket Unix persistente. Sem overhead TCP, sem headers HTTP duplicados, sem buffering desnecessário.

3. Nginx vs Caddy vs Traefik: Comparação

Característica Nginx Caddy Traefik
Linguagem C Go Go
FastCGI nativo Sim (excelente) Sim (v2.7+) Não
Autocert TLS Não (requer Certbot) Sim (built-in) Sim (Let’s Encrypt)
HTTP/3 (QUIC) Sim (1.25+) Sim (experimental) Sim
Configuração Arquivo .conf Caddyfile (simples) YAML/TOML/labels
Docker integration Manual Manual Automática (labels)
Hot reload Sim (nginx -s reload) Sim (caddy reload) Sim (automático)
Performance Máxima (C/ASM) Alta (Go) Alta (Go)
Ideal para Produção, alta carga, PHP Simplicidade, autocert Docker/Kubernetes

4. Configurar Nginx com FastCGI

# Nginx + PHP-FPM via FastCGI (Unix socket)

# /etc/nginx/sites-available/empresa.conf
upstream php-fpm {
    server unix:/run/php/php8.3-fpm.sock;
    # Ou TCP: server 127.0.0.1:9000;
}

server {
    listen 80;
    listen 443 ssl http2;
    server_name empresa.pt www.empresa.pt;

    ssl_certificate /etc/letsencrypt/live/empresa.pt/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/empresa.pt/privkey.pem;

    root /var/www/empresa;
    index index.php index.html;

    # FastCGI para PHP
    location ~ \.php$ {
        fastcgi_pass php-fpm;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;

        # Timeouts FastCGI
        fastcgi_connect_timeout 5s;
        fastcgi_read_timeout 60s;
        fastcgi_send_timeout 60s;

        # Buffering (desligar para streaming)
        fastcgi_buffering off;
        fastcgi_request_buffering off;

        # Buffers
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
    }

    # Proxy para backend Node.js/Python (HTTP, não FastCGI)
    location /api/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # Fichérios estáticos
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}
# Instalar Nginx + PHP-FPM no Ubuntu/Debian
sudo apt update
sudo apt install -y nginx php8.3-fpm php8.3-mysql php8.3-gd php8.3-curl

# ativar site
sudo ln -s /etc/nginx/sites-available/empresa.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

# Verificar PHP-FPM
sudo systemctl status php8.3-fpm

# Benchmark rápido
ab -n 1000 -c 10 https://empresa.pt/
# Com FastCGI: ~2000 req/s em hardware modesto

5. Configurar Caddy com PHP-FPM

# Caddyfile — muito mais simples que Nginx

empresa.pt {
    root * /var/www/empresa
    encode gzip zstd

    # FastCGI para PHP-FPM
    php_fastcgi unix//run/php/php8.3-fpm.sock {
        # Configuração equivalente ao Nginx
        # Caddy trata SCRIPT_FILENAME automaticamente
    }

    # Reverse proxy para API Node.js
    reverse_proxy /api/* 127.0.0.1:3000

    # Ficheiros estáticos
    file_server
    header Cache-Control "public, max-age=2592000"

    # TLS automático (Caddy pede e renova certificados Let's Encrypt)
    # Não precisas configurar nada — é automático
}

# Múltiplos sites
api.empresa.pt {
    reverse_proxy 127.0.0.1:3000
}

blog.empresa.pt {
    root * /var/www/blog
    php_fastcgi unix//run/php/php8.3-fpm.sock
    file_server
}
# Instalar Caddy
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install -y caddy

# Iniciar
sudo systemctl start caddy

# Caddy automaticamente:
# 1. Pede certificado Let's Encrypt
# 2. Configura TLS 1.3
# 3. Redirect HTTP -> HTTPS
# 4. Renova certificados automaticamente
# 5. Serve PHP via FastCGI
# 6. Serve ficheiros estáticos

# Hot reload após alterar Caddyfile
sudo caddy reload --config /etc/caddy/Caddyfile

6. Configurar Traefik com Docker

# docker-compose.yml com Traefik + WordPress + API Node.js

version: '3.8'
services:
  traefik:
    image: traefik:v3.2
    command:
      - --providers.docker=true
      - --providers.docker.exposedbydefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.http3=true
      - [email protected]
      - --certificatesresolvers.le.acme.storage=/acme.json
      - --certificatesresolvers.le.acme.tlschallenge=true
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"  # HTTP/3 QUIC
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./acme.json:/acme.json
    restart: always

  wordpress:
    image: wordpress:php8.3-fpm-alpine
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wp
      WORDPRESS_DB_PASSWORD: SubstituirPassword
    volumes:
      - wp-data:/var/www/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wp.rule=Host(`empresa.pt`)"
      - "traefik.http.routers.wp.tls=true"
      - "traefik.http.routers.wp.tls.certresolver=le"
      # Traefik não fala FastCGI nativamente — usa HTTP para o WordPress
      # Solução: usar Nginx como sidecar para FastCGI
      - "traefik.http.services.wp.loadbalancer.server.port=9000"
      # Nota: isto envia HTTP para o PHP-FPM que espera FastCGI
      # Para FastCGI real, precisa de Nginx sidecar
    depends_on:
      - db

  api:
    image: node:22-alpine
    command: node /app/server.js
    volumes:
      - ./api:/app
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.empresa.pt`)"
      - "traefik.http.routers.api.tls=true"
      - "traefik.http.routers.api.tls.certresolver=le"
      - "traefik.http.services.api.loadbalancer.server.port=3000"

  db:
    image: mariadb:11
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wp
      MYSQL_PASSWORD: SubstituirPassword
      MYSQL_ROOT_PASSWORD: SubstituirRootPassword
    volumes:
      - db-data:/var/lib/mysql

volumes:
  wp-data:
  db-data:

⚠ Nota: O Traefik não suporta FastCGI nativamente. Para WordPress/PHP com Traefik, usa Nginx como sidecar (fastcgi para PHP-FPM + HTTP para Traefik). O Caddy e Nginx suportam FastCGI directamente.

7. HTTP/3 e QUIC

O HTTP/3 usa QUIC (Quick UDP Internet Connections) em vez de TCP. Reduz latência em conexões instáveis (mobile, redes com perda de pacotes).

Característica HTTP/2 (TCP) HTTP/3 (QUIC)
Transporte TCP UDP
TLS TLS 1.3 Built-in (QUIC crypto)
Head-of-line blocking Sim (TCP) Não (streams independentes)
0-RTT Não Sim (resumo de sessão)
Multiplexação Sim (mas limitada pelo TCP) Sim (real)
# ativar HTTP/3 no Nginx (1.25+)
# Necessário compilar com --with-http_v3_module ou usar pacote que inclua

server {
    listen 443 ssl;
    listen 443 quic reuseport;  # HTTP/3
    http2 on;
    http3 on;
    server_name empresa.pt;

    ssl_certificate /etc/letsencrypt/live/empresa.pt/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/empresa.pt/privkey.pem;

    # Anunciar HTTP/3 no header Alt-Svc
    add_header Alt-Svc 'h3=":443"; ma=86400';

    # ... resto da configuração
}

# No Caddy, HTTP/3 é automático (experimental, pode necessitar flag)
# caddy run --config Caddyfile --experimental-http3

# No Traefik, ativar http3 no entrypoint (ver docker-compose acima)
# --entrypoints.websecure.http3=true

8. Terminação TLS e Autocert

# Caddy: TLS 100% automático
# O Caddy pede, instala e renova certificados Let's Encrypt
# Sem Certbot, sem cron, sem configuração extra
# Basta ter o domínio a apontar para o servidor

# Nginx: TLS com Certbot
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d empresa.pt -d www.empresa.pt
# Renovação automática via systemd timer
sudo systemctl status certbot.timer

# Traefik: TLS automático via labels
# labels:
#   - traefik.http.routers.site.tls=true
#   - traefik.http.routers.site.tls.certresolver=le
# O Traefik pede e renova automaticamente

# Verificar TLS
curl -vI https://empresa.pt 2>&1 | grep -i "ssl\|tls"
# Deve mostrar: TLSv1.3

# Verificar certificado
echo | openssl s_client -connect empresa.pt:443 -servername empresa.pt 2>/dev/null | openssl x509 -noout -dates

9. Benchmarks e Performance

Benchmarks aproximados (servidor 2 vCPU, 4GB RAM, Ubuntu 24.04, PHP 8.3, WordPress default):

Cenário Nginx + FastCGI Caddy + FastCGI Traefik + HTTP
Req/s (estático) ~12.000 ~9.000 ~7.000
Req/s (WordPress) ~2.200 ~1.900 ~1.500
Latência p50 ~5ms ~7ms ~9ms
Memória (idle) ~20MB ~30MB ~50MB
Configuração Complexa Muito simples Média (labels)

💡 Dica: A diferença de performance entre Nginx e Caddy é ~15-20%, mas o Caddy compensa com TLS automático e configuração 10x mais simples. Para a maioria das PMEs, Caddy é a melhor escolha. Para alta carga, Nginx.

10. Optimizar PHP-FPM

# /etc/php/8.3/fpm/pool.d/www.conf

# Process manager: dynamic (ajusta workers consoante carga)
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500  # Reinicia worker após 500 pedidos (previne memory leaks)

# Unix socket (mais rápido que TCP)
listen = /run/php/php8.3-fpm.sock
listen.owner = www-data
listen.group = www-data

# Buffer de FastCGI
listen.backlog = 65535

# Slow log (pedidos que demoram mais que X segundos)
request_slowlog_timeout = 5
slowlog = /var/log/php8.3-fpm/slow.log

# Calcular max_children:
# max_children = RAM_total / (RAM_per_worker)
# Exemplo: 4GB RAM, cada worker usa ~50MB
# max_children = 4096 / 50 = ~80
# Mas reservar RAM para OS/DB: usar 50

# Reiniciar PHP-FPM
sudo systemctl restart php8.3-fpm

# Verificar workers ativos
ps aux | grep php-fpm | grep -v grep | wc -l

11. Cenário Prático PME

Para uma PME que precisa de servir WordPress + API Node.js + site estático:

Componente Recomendado
Reverse proxy Caddy (simplicidade + autocert)
WordPress PHP-FPM 8.3 via FastCGI (Unix socket)
API Node.js reverse_proxy para 127.0.0.1:3000
Cache Redis + Caddy encode gzip/zstd
TLS Caddy autocert (Let’s Encrypt)
Se Docker Traefik (labels automáticos)

12. Boas Práticas

  • Usar Unix sockets para FastCGI — mais rápido que TCP (sem overhead de rede)
  • Desligar buffering para APIs que fazem streaming (fastcgi_buffering off)
  • Configurar slow log no PHP-FPM para detectar pedidos lentos
  • Usar OPcache — cache de bytecode PHP, reduz latency ~40%
  • Comprimir respostas — gzip ou zstd (Caddy suporta ambos nativamente)
  • Cache de estáticos — header Cache-Control com max-age adequado
  • HTTP/3 — reduzir latência em mobile e redes instáveis
  • Renovar TLS — usar TLS 1.3, desativar TLS 1.0/1.1
  • Rate limiting — proteger contra DDoS básico
  • Logs estruturados — JSON logs para integração com Grafana/ELK

13. Checklist de Implementação

  • ☐ Escolher reverse proxy (Caddy para simplicidade, Nginx para performance, Traefik para Docker)
  • ☐ Configurar FastCGI para PHP-FPM (Unix socket)
  • ☐ ativar TLS automático (Caddy built-in, Certbot para Nginx, ACME para Traefik)
  • ☐ Configurar reverse_proxy para APIs backend
  • ☐ ativar HTTP/3 se suportado
  • ☐ Optimizar PHP-FPM (pm.max_children, pm.max_requests)
  • ☐ ativar OPcache no PHP
  • ☐ Configurar compressão (gzip/zstd)
  • ☐ Configurar cache de ficheiros estáticos
  • ☐ Configurar rate limiting
  • ☐ ativar slow log no PHP-FPM
  • ☐ Testar com ab/wrk (benchmark)
  • ☐ Configurar logs estruturados
  • ☐ Documentar configuração

Artigos Relacionados

Inspirado na análise técnica de agwa.name sobre FastCGI vs HTTP para reverse proxies. Benchmarks aproximados para referencia — resultados reais dependem de hardware, configuração e workload. Licença: CC BY-SA 4.0.

Este artigo foi útil?

Duarte Spínola

Deixe um Comentário