Você confia no Redis? Eu também confiava. Até o dia em que um plugin de cupom gratuito transformou meu site num zumbi lento. Um erro de 500 por minuto, logs sem nexo, e uma missão de debugging que durou 72 horas. Aqui está o que aconteceu – e como evitar que isso aconteça com você.
O Cenário: Um Black Friday Silencioso
Era outubro de 2023. Um cliente (e-commerce de nicho com 2 milhões de sessões/mês) decidiu ativar um plugin de cupom promocional. O site usava WooCommerce, Redis como cache de objetos e transientes, e um banco MariaDB otimizado. Funcionava perfeitamente. Até que não.
“Os relatórios de performance mostravam picos de cpu em horários aleatórios, mas ninguém ligava os pontos. O time de marketing só queria o cupom ativo.”
— Engenheiro anônimo, em fórum privado
O plugin de cupom, gratuito, usava transientes para armazenar sessões de desconto. Nada incomum. Mas, ao invés de usar set_transient() com expiração adequada, ele criava transientes com chaves baseadas em user_id + random_hash. Isso gerou centenas de milhares de transientes únicos, todos armazenados no Redis. A cache encheu.
O Erro: Cache Corrompida e Queries Fantasmas
Quando o Redis atingiu o limite de memória, começou a fazer evicções. Mas o plugin não verificava se o transiente existia de fato. Ao tentar recuperar um transiente evictado, o código do plugin disparava uma query SQL para regenerá-lo. A query era algo como:
SELECT * FROM wp_postmeta WHERE meta_key = '_coupon_code' AND meta_value = 'DESCONTO10'
Em grande escala, isso se repetia milhares de vezes por minuto. O banco começou a acumular deadlocks. O pior: como o transiente sumia, o plugin tentava recriá-lo a cada request, gerando um ciclo vicioso de queries e evicções.
Sintomas Físicos (No Servidor)
- MySQL com 400+ conexões ativas – um pico de inatividade nunca visto;
- CPU do servidor web a 95% – porém sem tráfego real maior que o normal;
- Logs de erro com “Too many connections” – mas o pool estava configurado para 500;
- Redis com 3.2GB de uso – para um site que antes usava 800MB;
- Tempo de execução do WordPress: 45 segundos – para uma página simples.
O Diagnóstico: Como um Erro de Lógica Quase Matou o Site
Ao abrir os transientes no Redis, vi algo assustador: mais de 2 milhões de chaves com prefixo wpc_coupon_session_. Era o plugin. Ele criava um transiente para cada visitante anônimo, sem expiração. Sim, sem expiração. Aí estava o erro.
A solução imediata foi resetar o Redis com FLUSHALL e desativar o plugin. Em minutos, o site voltou ao normal. Mas o aprendizado ficou: cache não é salvação, é responsabilidade.
A Solução Definitiva: Regras de Negócio e Monitoramento
Depois do incidente, implementamos:
1. Limpeza Programada de Cache
Um script de cron que rodava a cada 30 minutos e deletava transientes com padrão wpc_coupon_session_* mais velhos que 1 hora. Nunca mais tivemos acúmulo.
2. Monitoramento de Cache no New Relic
Alertas para quando o número de chaves no Redis ultrapassasse 500 mil. Aviso antes do caos.
3. Substituição do Plugin
Um plugin pago e bem codificado, com uso correto de transientes expiráveis e cachê local com verificação de existência.
O erro foi corrigido. Mas a cicatriz ficou.
Lições para o Mundo WordPress
- Nunca confie em plugins gratuitos sem auditar o código de cache;
- Transientes sem expiração são uma bomba-relógio – principalmente em sites com alto tráfego;
- Redis não é infinito – monitore o uso e configure políticas de evicção (
allkeys-lrué seu amigo); - Logs mentem – o erro que vi foi “conexão perdida com o banco”. A causa real estava na cache.
A próxima vez que você ver um pico de CPU sem explicação, antes de culpar o servidor, olhe para o Redis. Pode ser que um plugin gratuito esteja fazendo um SQL fantasma.