Una base PostgreSQL rápida es una base cuyos datos consultados con frecuencia caben en memoria. Todo el dimensionamiento parte de ahí: el volumen de la base, la parte que trabaja realmente, el número de conexiones y, después, el disco y su margen. Esta guía da el método, los ajustes de partida para 4, 8 y 16 GB de memoria, y las consultas que miden una base existente.
shared_buffers al 25 % de la memoria, effective_cache_size al 75 %, random_page_cost = 1.1 en SSD NVMe.pg_dump, fuera del servidor, y restáurela con regularidad para comprobarla.La memoria de un servidor de base de datos sirve ante todo de caché: una página leída en memoria se sirve mucho más rápido que una página leída en disco, incluso NVMe. La pregunta es, por tanto, «¿qué parte se lee con frecuencia?», además de «¿cuánto pesa la base?». Una base de 50 GB en la que solo se consultan los últimos doce meses quizá trabaje sobre 8 GB.
En una base existente, dos consultas dan el volumen total y las tablas más grandes, índices incluidos:
SELECT pg_size_pretty(pg_database_size(current_database()));
SELECT relname AS nombre,
pg_size_pretty(pg_total_relation_size(relid)) AS tamano_con_indices
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;
Para una base futura, estime tabla por tabla: número de filas esperadas a un año × tamaño medio de una fila; después, añada los índices, que suelen pesar del 30 al 100 % de los datos. Ejemplo: 2 millones de filas al mes, de 500 bytes cada una, suman 12 GB de datos a un año, y de 18 a 24 GB con los índices.
PostgreSQL guarda las páginas leídas en dos niveles: su propia caché (shared_buffers) y la caché de archivos del sistema. Su documentación recomienda partir del 25 % de la memoria para shared_buffers en un servidor dedicado, y observa que por encima del 40 % la ganancia es poco frecuente: el resto beneficia a la caché del sistema y a las ordenaciones.
| Parámetro | 4 GB | 8 GB | 16 GB | Función |
|---|---|---|---|---|
shared_buffers | 1 GB | 2 GB | 4 GB | La caché propia de PostgreSQL |
effective_cache_size | 3 GB | 6 GB | 12 GB | La caché total estimada, que orienta la elección de los planes de consulta |
work_mem | 8 MB | 16 MB | 32 MB | La memoria de cada ordenación o hash, por conexión: hay que multiplicarla por las consultas simultáneas |
maintenance_work_mem | 256 MB | 512 MB | 1 GB | La creación de índices y el VACUUM |
random_page_cost | 1.1 | 1.1 | 1.1 | El coste estimado de una lectura aleatoria: 4 por defecto, muy por encima del coste real en SSD NVMe |
Estos valores suponen una base sola en el servidor. Si la aplicación funciona al lado, reste primero su memoria (procesos, caché, compilación) y aplique los porcentajes al resto: un servidor de 8 GB que ejecuta una aplicación de 3 GB se ajusta como una base de 5 GB.
shared_buffers = 2GB
effective_cache_size = 6GB
work_mem = 16MB
maintenance_work_mem = 512MB
random_page_cost = 1.1
shared_buffers solo surte efecto al reiniciar PostgreSQL; los demás parámetros se recargan sin interrupción, con SELECT pg_reload_conf();.
Para saber si la memoria basta, lea la tasa de lectura en caché. En una aplicación de gestión o un sitio web, supera el 99 %:
SELECT round(100.0 * blks_hit / nullif(blks_hit + blks_read, 0), 2) AS tasa_cache
FROM pg_stat_database
WHERE datname = current_database();
PostgreSQL abre un proceso por conexión, y acepta 100 por defecto (max_connections). Cada proceso ocupa unos pocos megabytes en reposo, y más cuando ordena datos o les aplica un hash (work_mem, a veces varias veces en una misma consulta). Subir max_connections a 500 para seguir el ritmo de una aplicación que abre muchas conexiones expone al servidor a quedarse sin memoria en el primer pico.
La respuesta adecuada es un pooler de conexiones: PgBouncer, en modo transaction, hace que cientos de conexiones de la aplicación compartan unas decenas de conexiones reales. Los frameworks también tienen su propio pool (SQLAlchemy, Prisma, HikariCP): ajuste su tamaño al número de vCPU del servidor de base de datos, más que al número de usuarios.
El disco de un servidor PostgreSQL contiene más que las tablas:
max_wal_size), más durante una importación masiva, y más aún si el archivado del registro se retrasa.work_mem.VACUUM FULL y la reconstrucción de un índice escriben una copia completa antes de liberar la antigua.La regla: el volumen a un año, más un 30 % de margen como mínimo. Este margen protege el servicio: cuando el disco que aloja el registro de transacciones se llena, PostgreSQL se detiene para proteger sus datos. Vigile la ocupación y amplíe antes del 80 %.
En cuanto al rendimiento, cada confirmación de transacción espera a que el registro se escriba en disco: la latencia del almacenamiento fija el caudal de escritura. Ahí es donde un SSD NVMe marca la diferencia, mucho más que en las lecturas, que la memoria ya sirve.
Una consulta de PostgreSQL se ejecuta en un solo núcleo, salvo las lecturas grandes que el motor paraleliza. El número de vCPU fija, por tanto, el número de consultas pesadas procesadas a la vez: 2 vCPU bastan para una aplicación de gestión en el lanzamiento, y de 4 a 8 convienen a las bases muy solicitadas y a los informes pesados.
Antes de añadir vCPU, busque las consultas que los consumen. La extensión pg_stat_statements las clasifica por tiempo total:
shared_preload_libraries = 'pg_stat_statements'
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
SELECT calls, round(total_exec_time) AS ms_total,
round(mean_exec_time::numeric, 1) AS ms_medio, query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
En el lanzamiento, la base de datos en el mismo servidor que la aplicación es la elección adecuada: ninguna latencia de red entre ambas, una conexión por socket Unix, un solo servidor que copiar y vigilar. Se separan cuando las dos se disputan los recursos: una compilación o un pico de tráfico que vacía la caché de la base, una base que necesita toda la memoria para sus datos, o exigencias de copia de seguridad diferentes.
listen_addresses = 'localhost' mientras solo se conecte la aplicación del servidor. Si otro servidor debe acceder, abra el puerto 5432 solo a su dirección, en el cortafuegos y en pg_hba.conf.scram-sha-256 en pg_hba.conf, un rol por aplicación, sin permisos de superusuario.pg_dump, copiada fuera del servidor.pg_dump -Fc -d mi_base -f mi_base-$(date +%F).dump
createdb mi_base_prueba
pg_restore -d mi_base_prueba mi_base-2026-10-29.dump
El VPS Pro funciona sobre procesadores Intel Xeon, memoria ECC que corrige los errores al vuelo y SSD NVMe en espejo, con cada bloque de datos verificado por suma de comprobación y una copia de seguridad cifrada cada noche, fuera de la máquina. La Asistencia integral está incluida: cuando su base de datos se ralentiza, analizamos las consultas lentas y los índices, y le indicamos los ajustes que devuelven a su aplicación toda su velocidad.
La suficiente para que los datos consultados con frecuencia quepan en memoria. Para una aplicación de gestión en el lanzamiento, 4 GB bastan, base de datos y aplicación incluidas. Después, mida la tasa de lectura en caché: mientras se mantenga por encima del 99 %, la memoria es suficiente.
El 25 % de la memoria en un servidor dedicado a la base de datos, como recomienda la documentación de PostgreSQL: 1 GB sobre 4 GB, 2 GB sobre 8 GB, 4 GB sobre 16 GB. Por encima del 40 %, la ganancia es poco frecuente, ya que la caché del sistema hace el resto.
PostgreSQL acepta 100 por defecto, y cada conexión es un proceso que consume memoria. En lugar de subir ese tope, coloque un pooler como PgBouncer delante de la base: unas decenas de conexiones reales atienden entonces a cientos de conexiones de la aplicación.
En el lanzamiento, mejor juntas: en el mismo servidor, la base responde sin latencia de red y el conjunto se copia de una sola vez. Se separan cuando una estorba a la otra, por ejemplo cuando una compilación o un pico de tráfico vacía la caché de la base.
Simafri
Hablemos de su proyecto
Díganos en pocas palabras lo que necesita: le respondemos rápidamente.
¡Gracias! Su solicitud ha sido enviada. Le responderemos en breve.
¿Prefiere el correo? Escríbanos a support@simafri.com.