Postgres é sensacional, é parrudo e todo mundo sabe que é o “queridinho” para dados hoje em dia. Mas ele não faz milagre. Se você tem uma aplicação que espanca o banco com queries repetitivas (aqueles SELECTs que não mudam quase nunca, mas rodam milhares de vezes por segundo), o seu I/O vai pro espaço, a CPU sobe e a latência vira um pesadelo.
Recentemente, trabalhei em uma adaptação do PG_Dog (um proxy/pooler focado em Postgres) para resolver exatamente esse problema. O “pulo do gato”? Coloquei uma camada de cache chave-valor usando #Redis em paralelo ao pooler.
Por que colocar cache no Pooler?
Se a sua aplicação é legada ou se você tem um time de dev que não quer (ou não pode) mexer no código para implementar cache, você resolve isso no “meio do caminho”. O PG_Dog intercepta a query, vê se ela já foi feita antes e entrega o resultado na velocidade da memória.
A vantagem de usar Redis com Sharding em paralelo é que a gente não cria um novo gargalo. Se um nó de Redis ficar cheio ou sobrecarregado, a carga está distribuída entre vários shards.

Como a mágica acontece?
Basicamente, a estrutura funciona assim:
- Identificação: A aplicação manda a query pro PG_Dog.
- Hashing: O PG_Dog gera um hash único baseado no SQL e nos parâmetros. Esse hash é a chave.
- Check de Cache: Ele consulta os #shards do Redis em paralelo.
- Cache Hit: Se o dado estiver lá, ele devolve pro usuário em <5ms. O Postgres nem acorda.
- Cache Miss: Se não estiver, ele executa no Postgres, popula o Redis para a próxima e entrega o resultado.
Invalidação?
Claro que temos, funciona assim:
- Identificação: A aplicação manda o DML ou DDL pro PG_Dog.
- Check de Cache: Ele consulta os #shards do Redis em paralelo.
- Cache Delete Se a tabela estiver lá ele deleta a chave ou chaves envolvidas.
- No Commit: Se uma transação for aberta mas não comitada eu não limpo o cache.
Por que cache externo?
A vantagem de ter um pooler é poder escalar ele horizontalmente, afinal, não queremos gerar um ponto único de falha no ambiente.
Mas, estalar ele horizontal implica em trazer um outro problema para a mesa, um select pode criar um cache para aquele select, mas e se um DML ou DDL usar um outro pooler para fazer a alteração, como invalidar esse cache para evitar um falso positivo? por isso a ideia de usar um Redis (ou qualquer outro cache que use a mesma tecnologia) externo ao pooler.
O container do pooler fica pequeno e você escala o cache da melhor forma possível. (Shard, Cluster, Single, aí é com você).
Configuração (Mão na massa)
Não adianta só falar, tem que mostrar como configura. No arquivo de configuração do seu PG_Dog (que agora aceita múltiplos backends de cache), a coisa fica mais ou menos assim:
YAML
# Exemplo de config do PG_Dog com Redis Sharding
[result_cache]
enabled = true
# Redis/Valkey/Dragonfly connection URL.
redis_url = "redis://127.0.0.1:6379"
# TTL (seconds). If omitted, PgDog applies a default.
expire_seconds = 30
# Don't cache very large results.
max_entry_bytes = 524288
# Redis key prefix.
key_prefix = "pgdog:result_cache"
# Optional allow/deny lists (regex) to control what gets cached.
# Unsafe lists take precedence over safe lists.
cache_safe_schema_list = []
cache_unsafe_schema_list = []
cache_safe_table_list = []
cache_unsafe_table_list = []
Na configuração acima você pode ver que da pra personalizar como no PG_Pool2, não fazer cache de tabelas específicas ou de schemas específicos, e por sinal, da pra usar regex caso precise.
Conclusão
Essa adaptação transforma o PG_Dog em uma ferramenta de aceleração ativa. Você ganha fôlego no banco de dados principal, economiza em instância de nuvem (RDS/CloudSQL).
O código está aberto para quem quiser testar, quebrar ou melhorar lá no meu GitHub:
Ainda estou em fase de testes totalmente Alfa, se alguém tiver coragem de começar a testar e ir encontrando erros é só avisar.



