OpenAI: estratégia de escalabilidade massiva do PostgreSQL para sustentar 800 milhões de usuários
(openai.com)Resumo:
- A OpenAI está processando milhões de QPS e 800 milhões de usuários com um único Primary e cerca de 50 Read Replicas (Azure Flexible Server).
- Para distribuir a carga de escrita, workloads que podem ser shardados foram migrados para o Azure Cosmos DB, e escritas foram otimizadas no nível da aplicação com técnicas como
Lazy Write. - A adoção do PgBouncer reduziu a latência de conexão de 50 ms para 5 ms, e foi implementado um mecanismo de cache lock para evitar tempestades de cache miss.
- A estabilidade foi garantida por meio da remoção de consultas com joins complexos, timeouts rígidos de menos de 5 segundos para alterações de esquema e isolamento de workloads conforme a prioridade do tráfego.
Resumo detalhado:
1. Contexto e situação atual da arquitetura
O tráfego de PostgreSQL da OpenAI cresceu mais de 10 vezes no último ano e agora atende 800 milhões de usuários e milhões de QPS (consultas por segundo). Surpreendentemente, essa escala é operada com uma estrutura de um único Primary e cerca de 50 Read Replicas distribuídas pelo mundo. Para evitar que o design inicial começasse a falhar, a OpenAI realizou grandes otimizações tanto na infraestrutura quanto na camada de aplicação.
2. Principais gargalos resolvidos e estratégias de otimização
-
Distribuição da carga de escrita:
- A estrutura de writer único do PostgreSQL tem limites de escalabilidade, além do problema de amplificação de escrita causado por MVCC (controle de concorrência multiversão).
- Como solução, workloads intensivos em escrita que podem ser particionados horizontalmente (sharding) foram migrados para sistemas como o Azure Cosmos DB.
- No PostgreSQL existente, a criação de novas tabelas foi proibida, e a carga no Primary foi minimizada com correções de bugs na aplicação e a adoção de Lazy Write (adiar escritas para suavizar picos de tráfego).
-
Otimização de consultas e gerenciamento de ORM:
- Houve no passado um caso em que uma consulta com join de 12 tabelas causou uma falha crítica (SEV), por isso joins múltiplos complexos passaram a ser evitados e a lógica foi separada para a aplicação.
- As consultas ineficientes geradas pelo ORM são revisadas continuamente, e a configuração
idle_in_transaction_session_timeoutfoi aplicada para impedir que consultas ociosas bloqueiem o Autovacuum.
-
Pooling de conexões (PgBouncer):
- Para evitar o limite de conexões do Azure PostgreSQL (5.000) e rajadas de conexões, o PgBouncer foi implantado como camada de proxy.
- Foram usados os modos de pooling por transação e por instrução (statement) para aumentar o reaproveitamento de conexões, reduzindo o tempo médio de conexão de 50 ms para 5 ms.
-
Prevenção de cache miss (Cache Locking):
- Para evitar o problema de thundering herd, em que inúmeras requisições correm para o banco ao mesmo tempo quando o cache expira, foi introduzido um mecanismo de cache lock (leasing).
- Quando ocorre um cache miss para uma chave específica, apenas uma única requisição obtém o lock e acessa o banco para atualizar os dados, enquanto as demais aguardam, bloqueando assim a sobrecarga no DB.
3. Estabilidade e políticas operacionais
- Mitigação de ponto único de falha (SPOF): Mesmo em caso de falha do Primary, as requisições de leitura continuam sendo atendidas pelas Replicas, reduzindo a gravidade do incidente. O Primary também mantém um Hot Standby em modo de alta disponibilidade (HA) para garantir failover rápido.
- Isolamento de workloads: Para evitar o problema de noisy neighbor, o tráfego é roteado para instâncias separadas conforme a importância (Low/High Priority).
- Gerenciamento rigoroso de esquema: Alterações que provoquem reescrita completa de tabela (Full Table Rewrite) são proibidas, e mudanças de esquema aplicam um timeout rígido de 5 segundos para evitar lentidão no serviço.
4. Planos futuros (The Road Ahead)
Embora a estrutura atual já tenha escalabilidade suficiente, a OpenAI está testando Cascading Replication para expandir ainda mais o número de Read Replicas, substituindo o modelo em que o Primary envia WAL para todas as Replicas por outro em que Replicas intermediárias repassam o WAL para as inferiores. No longo prazo, o sharding do próprio PostgreSQL também está sendo considerado.
2 comentários
Resumo da discussão no Hacker News: https://news.ycombinator.com/item?id=46725300
A imponência de uma instância única: houve muitas reações reafirmando a validade do escalonamento vertical, com comentários como "Big DB servers are your friend", sobre o fato de processarem tráfego na escala de 800 milhões de usuários com um único Postgres (write), sem sharding.
A ironia de sharding vs. refatoração: sobre o trecho do texto que diz "não escolheram sharding porque refatorar o app existente era complexo demais", circularam piadas e críticas mordazes do tipo "é irônico que uma empresa que vende IA para programação diga que não consegue refatorar porque é difícil". (Por outro lado, também houve defesas de que é uma escolha racional ao considerar a complexidade operacional e o custo de migração que o sharding traria.)
Frustração com a profundidade técnica: como o texto se concentra mais em conteúdos genéricos, como cache e connection pooling, houve também uma visão crítica de que faltam detalhes concretos de engenharia e de que "parece um texto promocional".
Discussão relacionada a Rust: nos comentários, independentemente do texto principal, também houve compartilhamento de técnicas para bloquear na origem o problema de "Idle Transaction" usando verificações em tempo de compilação do Rust, o que levou a uma discussão técnica mais aprofundada.
Pessoalmente, achei interessante a parte em que aplicaram uma estrutura como Cascading Replication ou superaram limitações técnicas por meio da operação. Sobre isso, organizei minhas ideias com mais detalhes no Facebook. https://www.facebook.com/share/p/1Kp8V917bL/