Cache de arquivos estáticos com Nginx
Servir arquivos estáticos diretamente pelo Nginx — sem passar pelo Node.js ou Python — é 10-100x mais rápido. Com cache de proxy configurado, o Nginx armazena respostas do backend e as serve para requisições subsequentes sem chegar na aplicação. Isso reduz latência, carga no backend e consumo de memória.
Servir arquivos estáticos diretamente
Para arquivos que ficam no disco da VPS, sirva direto pelo Nginx:
server {
listen 443 ssl http2;
server_name seudominio.com.br;
# Diretório raiz dos estáticos
root /var/www/html;
# Servir arquivos estáticos sem passar pelo backend
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|webp|woff|woff2|ttf|eot)$ {
expires 1y; # cache por 1 ano no browser
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
access_log off; # não logar para economizar IO
try_files $uri =404;
}
# HTML: sem cache (sempre servir versão atualizada)
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
# API: sem cache
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Tentar arquivo estático, fallback para a app
location / {
try_files $uri $uri/ @app;
}
location @app {
proxy_pass http://127.0.0.1:3000;
}
}Proxy cache: armazenar respostas do backend
O Nginx pode cachear respostas HTTP do backend em disco:
# /etc/nginx/nginx.conf — dentro do bloco http {}
proxy_cache_path /var/cache/nginx
levels=1:2
keys_zone=api_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
# No bloco server:
server {
location /api/produtos {
# Cachear respostas GET por 5 minutos
proxy_cache api_cache;
proxy_cache_valid 200 5m;
proxy_cache_valid 404 1m;
proxy_cache_methods GET HEAD;
proxy_cache_key "$scheme$request_method$host$request_uri";
# Usar cache mesmo quando backend estiver offline
proxy_cache_use_stale error timeout updating http_500 http_502 http_503;
proxy_cache_background_update on;
proxy_cache_lock on; # apenas 1 req passa ao backend por key (thundering herd)
# Adicionar header mostrando se veio do cache
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://127.0.0.1:3000;
}
}Compressão gzip e brotli
Comprimir respostas reduz o tamanho em 60-80% para texto/JSON:
# /etc/nginx/conf.d/compression.conf
# Gzip (suporte universal)
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6; # nível 1-9: 6 é bom balanço velocidade/compressão
gzip_min_length 1024; # não comprimir arquivos < 1 KB
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml
font/woff
font/woff2;
# Brotli (melhor compressão que gzip, suporte browsers modernos)
# Requer módulo ngx_brotli (não incluído por padrão):
# sudo apt install libbrotli-dev
# Compilar Nginx com --add-module=ngx_brotli
# Ou usar nginx-extra: sudo apt install nginx-extras
brotli on;
brotli_comp_level 6;
brotli_types
text/plain
text/css
application/javascript
application/json
image/svg+xml;
# Servir arquivos pré-comprimidos (.gz ou .br) se existirem:
gzip_static on;
# brotli_static on;Invalidar o proxy cache
Limpar o cache quando o conteúdo do backend é atualizado:
# Limpar cache por chave específica:
sudo find /var/cache/nginx -type f -name "*.cache" | head -10
# Limpar todo o cache de uma zona:
sudo rm -rf /var/cache/nginx/*
sudo nginx -s reload
# Purge seletivo com ngx_cache_purge (módulo third-party):
# Adicionar ao location:
location ~ /purge(/.*) {
allow 127.0.0.1;
deny all;
proxy_cache_purge api_cache $scheme$request_method$host$1;
}
# Chamar a partir do deploy script:
curl -X PURGE http://127.0.0.1/purge/api/produtos
# Forçar bypass do cache (sem purge) — útil para testes:
location /api/ {
# Bypass se o header X-No-Cache estiver presente:
proxy_cache_bypass $http_x_no_cache;
proxy_no_cache $http_x_no_cache;
proxy_cache api_cache;
proxy_pass http://127.0.0.1:3000;
}
# Testar: curl -H "X-No-Cache: 1" https://api.seudominio.com.br/api/produtosVerificar eficiência do cache
Monitorar o hit rate e identificar o que está sendo cacheado:
# Verificar o header X-Cache-Status na resposta:
curl -I https://api.seudominio.com.br/api/produtos
# X-Cache-Status: MISS → primeira requisição, foi ao backend
# X-Cache-Status: HIT → servido do cache
# X-Cache-Status: EXPIRED → cache expirado, foi ao backend
# X-Cache-Status: STALE → cache expirado mas backend offline
# X-Cache-Status: BYPASS → forçado a ir ao backend
# Calcular hit rate nos logs:
sudo awk '{print $NF}' /var/log/nginx/access.log \
| grep -oP 'X-Cache-Status: \K\w+' \
| sort | uniq -c
# Alternativa — logar o cache status:
log_format cache_log '$remote_addr - [$time_local] "$request" $status '
'$upstream_cache_status "$http_referer"';
access_log /var/log/nginx/cache.log cache_log;
# Tamanho atual do cache em disco:
sudo du -sh /var/cache/nginx/$ runstack deploy --plan starter
Não quer configurar manualmente?
Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.