Síguenos

Tecnología

Así sostiene OpenAI ChatGPT con un solo PostgreSQL primario

La escala no depende de una base exótica, sino de réplicas, control de carga y decisiones operativas muy estrictas.

Publicado

el

Cómo escala OpenAI PostgreSQL

ChatGPT funciona sobre una arquitectura que, en su pieza central, resulta menos exótica de lo que cabría imaginar: un único servidor primario de PostgreSQL recibe las escrituras, mientras casi 50 réplicas distribuidas por distintas regiones absorben buena parte de las lecturas. OpenAI ha explicado que esa configuración sostiene millones de consultas por segundo para un servicio con 800 millones de usuarios, con una latencia de dos dígitos bajos en milisegundos y una disponibilidad declarada del 99,999 %.

La cifra llamativa no cuenta toda la historia. El rendimiento no sale de dejar una base de datos convencional trabajando sin más, sino de reducir qué tareas llegan hasta ella, reutilizar conexiones, repartir las consultas según su importancia y poner límites para que un pico no se convierta en una caída en cadena. La decisión central ha sido aplazar el sharding del PostgreSQL principal y corregir los puntos de presión concretos antes de dividir los datos entre fragmentos.

La experiencia también muestra el reverso de esa estrategia: un solo escritor simplifica la operación, pero no elimina los límites de escritura ni convierte PostgreSQL en la respuesta adecuada para cualquier carga. OpenAI ha ido apartando ciertos trabajos intensivos en escrituras hacia otros sistemas y mantiene controles estrictos sobre cambios, consultas y mantenimiento. La escala depende tanto de lo que el equipo decide no enviar a la base de datos como de la potencia de la propia base.

Una arquitectura sencilla en el centro, no en los bordes

El clúster principal se ejecuta sobre Azure Database for PostgreSQL Flexible Server. El servidor primario procesa las escrituras y las réplicas de lectura se ocupan de las consultas que pueden atenderse fuera de él. En términos sencillos, la base conserva un punto central para modificar los datos, pero permite que muchas copias actualizadas respondan a solicitudes de lectura. Es una arquitectura primaria-réplicas llevada a una escala poco habitual, no una base de datos distribuida que reparta automáticamente cualquier operación.

La distinción importa porque añadir réplicas ayuda sobre todo cuando abundan las lecturas. No hace que el primario escriba en paralelo en 50 lugares ni multiplica por 50 su capacidad para registrar cambios. Las modificaciones siguen convergiendo en el escritor, y algunas lecturas también deben ir allí cuando forman parte de una transacción que acaba de escribir. Por eso el sistema intenta enviar a las réplicas todo lo que puede, pero conserva en el primario las operaciones que necesitan esa relación inmediata con la escritura. El diseño alivia el cuello de botella de lectura, no borra el límite de escritura.

Las réplicas, además, se distribuyen geográficamente para acercar el procesamiento a las aplicaciones y reducir los costes de comunicación entre regiones. No todas reciben la misma clase de trabajo: las consultas críticas para mostrar una conversación pueden ir a destinos con menos carga, mientras las tareas menos sensibles al tiempo se asignan a réplicas con más actividad. Esa separación reduce el riesgo de que una operación analítica o interna perjudique la respuesta que espera el usuario. La ubicación y la prioridad forman parte del rendimiento tanto como el número de servidores.

Por qué no fragmentar la base de datos principal

El sharding divide los datos entre varias bases o fragmentos, de modo que cada uno almacena y procesa una parte. Puede aumentar la capacidad de escritura y evitar que un único servidor concentre todo el trabajo, pero obliga a la aplicación a saber dónde vive cada dato. En un sistema grande, eso puede implicar revisar cientos de puntos de acceso, adaptar consultas que presuponen una base común y sostener una migración compleja mientras el servicio sigue funcionando. El coste no es solo instalar más servidores: es cambiar la lógica que depende de ellos.

OpenAI ha considerado más pragmático mantener el PostgreSQL central sin particionarlo por ahora. Según el análisis publicado, modificar cientos de endpoints y gestionar una transición entre el esquema antiguo y el nuevo supondría meses de trabajo, además de introducir nuevas posibilidades de error. Si las lecturas representan la mayor parte de la carga, repartirlas entre réplicas puede ofrecer margen sin asumir de inmediato el coste operativo de fragmentar toda la base. No se trata de afirmar que el sharding sea innecesario para siempre, sino de que el beneficio actual no compensa aún la complejidad.

Eso no significa que todas las escrituras se queden en PostgreSQL. La compañía ha trasladado determinados trabajos de escritura intensiva a Azure Cosmos DB cuando encajan mejor con un modelo de documentos y pueden separarse del núcleo relacional. La lógica restante permanece en PostgreSQL. Así se evita tanto forzar al servidor principal a absorberlo todo como rediseñar de una vez una aplicación entera. La estrategia es sacar los casos que presionan más, no reemplazar PostgreSQL por principio.

Réplicas, caché y el tráfico que nunca llega al escritor

La mayor parte del trabajo de lectura se puede aliviar antes de que toque el primario. Las cachés guardan datos que se consultan con frecuencia y las réplicas responden a muchas de las peticiones restantes. Cuando ambas capas funcionan, PostgreSQL no tiene que volver a calcular o recuperar desde el origen cada dato solicitado. En una plataforma con un volumen tan grande, esa diferencia convierte una consulta repetida en una respuesta servida desde una capa más ligera. La base central se protege reduciendo la demanda que recibe, no solo ampliando su tamaño.

Pero una caché también puede fallar de una manera peligrosa: si muchas solicitudes buscan a la vez una clave que acaba de caducar o no está disponible, todas pueden dirigirse a la base de datos para pedir el mismo contenido. Es el llamado estampido de fallos de caché. OpenAI describe un mecanismo de bloqueo para que una única solicitud obtenga el dato y repueble la caché, mientras las demás esperan en vez de disparar consultas redundantes. El objetivo es impedir que una ausencia puntual en la caché se convierta en una avalancha contra PostgreSQL.

La protección se completa con límites de velocidad en distintas capas: desde el borde de la red y la puerta de entrada de la API hasta la aplicación y la propia base de datos, donde pueden limitarse conexiones o duración de consultas. Esto importa especialmente cuando un servicio empieza a responder lento. Si los clientes reintentan demasiado pronto, cada fallo genera más tráfico y la latencia alimenta una espiral de nuevas solicitudes. Los límites y los reintentos controlados evitan que la respuesta automática a un problema lo agrave.

PgBouncer reduce el coste de abrir conexiones

Una consulta puede ser rápida y, aun así, perder tiempo antes de empezar. PostgreSQL crea un proceso para atender cada conexión, de modo que miles de conexiones simultáneas procedentes de muchos pods de aplicación pueden consumir recursos y alcanzar los límites disponibles. OpenAI explica que el establecimiento de conexiones llegaba a añadir alrededor de 50 milisegundos. Para una operación breve, ese tiempo puede ser comparable o superior al que tarda la propia consulta. El cuello de botella estaba, en parte, en entrar en la base, no en ejecutar SQL.

La solución es PgBouncer, un agrupador de conexiones que mantiene conexiones ya abiertas y las presta a las aplicaciones según se necesitan. Cuando una operación termina, la conexión puede volver al conjunto y servir a otra petición. En las pruebas descritas por la compañía, el tiempo de conexión bajó de unos 50 milisegundos a unos 5. La mejora no procede de un cambio en el motor de PostgreSQL, sino de evitar repetir una tarea costosa cada vez que una aplicación necesita acceder a los datos. La reutilización de conexiones reduce espera y amortigua las ráfagas de demanda.

El agrupamiento requiere ajustes cuidadosos: si los tiempos de espera o el tamaño de los pools no están bien calibrados, el intermediario puede convertirse en otro punto de congestión. También importa mantener cerca, dentro de lo posible, los proxies, las aplicaciones y las réplicas que intercambian tráfico, porque las conexiones entre regiones consumen tiempo y recursos. PgBouncer no es una solución mágica ni exclusiva de empresas gigantes; su valor aquí está en aplicar una herramienta conocida con una configuración acorde a una carga extraordinaria. La pieza es antigua; lo decisivo es integrarla bien en el recorrido de cada consulta.

Consultas más pequeñas y menos trabajo innecesario

Una consulta generada por un ORM puede parecer cómoda en el código y resultar muy costosa al ejecutarse. OpenAI identificó casos en los que el ORM producía uniones de hasta 12 tablas. Las relaciones entre modelos se encadenaban y el sistema pedía a PostgreSQL que reuniera muchos datos de una vez. Una consulta así puede consumir más CPU y ser más difícil de optimizar que varias operaciones acotadas. La abstracción del ORM no garantiza que el SQL resultante sea eficiente.

En algunos casos, el equipo trasladó parte de esa lógica a la aplicación y sustituyó una unión amplia por consultas más simples, cuyos resultados se combinan en el código. La decisión no implica que separar consultas sea siempre más rápido: puede aumentar los viajes a la base si se aplica sin criterio. Pero cuando una unión compleja se repite masivamente o consume demasiados recursos, dividir el trabajo puede facilitar la caché, el diagnóstico y el control de cada operación. La lección es revisar qué ejecuta realmente la aplicación, no juzgar su eficiencia por la elegancia del modelo.

Este tipo de optimización también permite detectar con más facilidad qué parte está lenta o falla. Si una petición depende de una única consulta enorme, el problema queda concentrado en una pieza difícil de aislar; en cambio, las operaciones separadas hacen más visible qué dato o relación está provocando la demora. El equipo puede decidir entonces qué resultados conviene reutilizar y qué consultas deben permanecer cerca de una escritura. La sencillez del SQL puede dar más margen para depurar y distribuir la carga.

MVCC y el precio de las escrituras

PostgreSQL utiliza control de concurrencia multiversión, conocido como MVCC. Cuando se actualiza una fila, el sistema conserva versiones para que las transacciones puedan trabajar sin bloquearse constantemente entre sí. Esa capacidad es fundamental, pero las escrituras frecuentes generan versiones antiguas que después deben limpiarse. A medida que se acumulan, aumentan el trabajo de mantenimiento de tablas e índices y pueden hacer que algunas lecturas revisen más información de la necesaria. En cargas intensivas, escribir un dato implica también gestionar sus versiones y su limpieza posterior.

Por eso OpenAI intenta reducir escrituras redundantes y emplea escrituras diferidas cuando el caso lo permite, además de trasladar ciertos trabajos a sistemas alternativos. El autovacuum, encargado de mantener bajo control las versiones obsoletas, también necesita condiciones adecuadas para funcionar. Una transacción que permanece abierta e inactiva puede impedir que avance parte de esa limpieza y contribuir al crecimiento de tablas e índices. Parámetros como idle_in_transaction_session_timeout cierran sesiones que se quedan paradas dentro de una transacción. Evitar conexiones inactivas no es solo ahorrar recursos: ayuda a que el mantenimiento interno siga su curso.

El control de las escrituras explica por qué algunos procesos se ralentizan deliberadamente. Rellenar una columna para una población enorme de registros con una única actualización masiva podría elevar de golpe la carga de lectura, escritura y disco. En su lugar, los backfills se ejecutan con límites de velocidad y pueden prolongarse durante semanas. El ritmo lento es intencional: permite que la operación avance sin competir de forma descontrolada con el tráfico cotidiano. En una base crítica, tardar más en una tarea secundaria puede ser la forma más rápida de evitar una interrupción.

Cambios de esquema diseñados para fallar rápido

Modificar la estructura de una tabla puede exigir un bloqueo. Si una operación de cambio espera a que termine una transacción larga, otras consultas pueden quedar detenidas detrás de ella. Por eso OpenAI aplica un tiempo límite estricto de cinco segundos para adquirir ciertos bloqueos durante cambios de esquema. Si no se consigue en ese plazo, la migración se aborta y puede volver a intentarse, en vez de permanecer esperando y bloquear tráfico nuevo. El criterio es fallar pronto antes que dejar una migración esperando indefinidamente.

La compañía también restringe los cambios que pueden forzar la reescritura completa de una tabla y permite crear o eliminar índices de forma concurrente cuando corresponde. Según lo descrito, además, ya no incorpora tablas nuevas al clúster principal y orienta los nuevos trabajos hacia sistemas fragmentados. No es una regla universal para cualquier instalación de PostgreSQL: refleja el esfuerzo por conservar estable un recurso que ya sostiene una parte esencial del servicio. La disciplina sobre el esquema limita el riesgo acumulado de cambios aparentemente pequeños.

Estas restricciones tienen un coste: los equipos disponen de menos libertad para añadir estructuras directamente al núcleo existente y deben evaluar dónde encaja cada función. A cambio, se reduce la posibilidad de que una nueva necesidad de producto convierta el servidor principal en un depósito de responsabilidades cada vez más difíciles de mantener. En una plataforma ya madura, la estabilidad no surge de evitar toda evolución, sino de separar el cambio que puede hacerse con seguridad del que conviene mantener fuera. La arquitectura también se gobierna mediante políticas de ingeniería, no solo con configuración técnica.

Alta disponibilidad y el riesgo de un único escritor

Con un primario, las escrituras dependen de un punto central. Si ese servidor deja de estar disponible, la capacidad de modificar datos se ve afectada. OpenAI mantiene una configuración de alta disponibilidad con una instancia en espera activa, preparada para asumir el papel principal ante una caída o durante tareas de mantenimiento. La compañía también señala que las lecturas críticas pueden seguir sirviéndose desde réplicas, lo que ayuda a contener el impacto, aunque no equivale a que todas las funciones continúen sin cambios. La redundancia reduce el tiempo de interrupción, pero no elimina la dependencia del primario.

Esta distinción evita interpretar el número de réplicas como una garantía de que cualquier fallo sea invisible. Una réplica de lectura sirve para escalar consultas y puede participar en una recuperación, pero la promoción de un servidor y la continuidad de las escrituras requieren una gestión específica. La disponibilidad depende tanto de que exista una copia como de que el cambio de función sea seguro y los datos estén suficientemente sincronizados. La tolerancia a fallos se mide por la capacidad de recuperarse sin perder el control del sistema.

OpenAI informó de un incidente SEV-0 relacionado con PostgreSQL durante los 12 meses descritos, asociado al lanzamiento viral de ImageGen. En una semana se sumaron 100 millones de usuarios y la actividad de escritura aumentó de forma abrupta. Es un episodio que ilustra por qué las consultas habituales no bastan para definir la capacidad necesaria: una novedad puede alterar el patrón de carga de manera repentina. El sistema debe resistir también los picos que nacen del éxito de una función.

El límite de las réplicas y la replicación en cascada

Las réplicas reciben los cambios del primario mediante el WAL, el registro secuencial de operaciones que PostgreSQL utiliza para reproducir modificaciones. Cada destino adicional necesita recibir esos datos, por lo que multiplicar las réplicas también aumenta la presión sobre la red y el trabajo de envío desde el escritor. Cerca de 50 réplicas pueden ser manejables con suficiente capacidad, pero el mismo método no se amplía indefinidamente sin coste. Escalar lecturas horizontalmente también añade carga al sistema que genera y distribuye las escrituras.

La replicación en cascada busca cambiar ese patrón. En vez de que el primario envíe los cambios directamente a todas las réplicas, puede alimentar un conjunto intermedio que retransmita el WAL a otras copias. La estructura se parece más a un árbol que a una estrella y podría permitir añadir más réplicas sin que el primario tenga que atenderlas a todas por separado. OpenAI ha descrito este trabajo como una iniciativa en desarrollo junto con Azure, no como una capacidad ya desplegada plenamente. La propuesta promete ampliar el alcance, pero introduce nuevas dependencias entre réplicas.

Ese matiz explica por qué la empresa no plantea la cascada como una mejora gratuita. Si una réplica intermedia falla o queda retrasada, las copias que dependen de ella pueden verse afectadas; también hay que asegurar que la conmutación por error funcione correctamente. El diseño en árbol puede rebajar presión en el origen, pero complica la operación y exige probar escenarios de fallo antes de llevarlo a producción. Más escala solo es útil si la recuperación sigue siendo fiable.

Lo que revela esta estrategia sobre escalar software

La experiencia de OpenAI no demuestra que cualquier empresa pueda atender cientos de millones de usuarios con una instalación convencional ni que PostgreSQL sea siempre la mejor opción. La carga, la mezcla de lecturas y escrituras, la forma de los datos, el equipo y la infraestructura cambian el resultado. Tampoco las cifras declaradas por la compañía describen el rendimiento de cada petición individual: millones de consultas por segundo, latencia de dos dígitos bajos y disponibilidad del 99,999 % son medidas agregadas de un sistema concreto. Los números muestran lo que ha conseguido ese diseño, no una receta trasladable sin cambios.

Lo que sí deja claro es que la escala no depende necesariamente de adoptar desde el principio la arquitectura más compleja disponible. OpenAI conserva un escritor central porque, según su evaluación, el coste de fragmentar toda la aplicación todavía supera el beneficio inmediato. A la vez, introduce límites, elimina consultas problemáticas, deriva ciertas escrituras, separa cargas por prioridad y se prepara para que la replicación no ahogue al servidor principal. La simplicidad que se ve en el diagrama descansa sobre una operación muy disciplinada.

La pregunta útil para otros equipos no es si deben copiar exactamente esta arquitectura, sino dónde se consume de verdad su capacidad: en conexiones, consultas mal construidas, escrituras innecesarias, picos de caché o cambios de esquema. Si el problema está en una consulta que reúne demasiadas tablas, cambiar todo el sistema de bases de datos puede añadir complejidad sin resolver la causa. Si el límite está en las escrituras, en cambio, sumar réplicas de lectura no bastará. La decisión acertada empieza por identificar el cuello de botella real, no por asumir que una tecnología más nueva lo hará desaparecer.

Newsletter

Periodista internacional con más de 20 años de experiencia en radio, prensa y medios digitales. Licenciado en Ciencias de la Comunicación, trabaja entre España e Italia con la mirada puesta en la actualidad.

Lo más leído