El benchmark detrás del post "Postgres isn't slow, your storage is" no es nuevo: el recap del talk salió el 20 de agosto de 2026 y el artículo ampliado el 21 de septiembre. Y deja una pregunta incómoda: ¿cuánto de lo que llamás "Postgres lento" es en realidad latencia de disco?
El benchmark de Postgres sobre NVMe local contra disco de red es una comparación publicada por ClickHouse, presentada en POSETTE 2026, que mide el mismo PostgreSQL con el mismo hardware cambiando solo el almacenamiento. Con NVMe local obtuvo una mediana de 16.030 TPS; con un volumen SSD de red, 1.734 TPS. Sirve a quien opera Postgres con cargas de escritura intensivas y datasets mayores a la RAM.
¿Qué midió exactamente el benchmark de ClickHouse?

Comparó ocho clústeres PostgreSQL idénticos: cuatro con NVMe local y cuatro con un volumen de red. Según el recap del talk de POSETTE 2026, la mediana fue de 16.030 TPS en NVMe contra 1.734 TPS en disco de red: una diferencia de 9,24×.
- Hardware: instancias de 16 vCPU y 64 GiB de RAM, con
shared_buffersde 16 GiB. El almacenamiento era lo único que cambiaba. - Dataset: una tabla
pgbench_accountsde 482 GiB con 3.300 millones de filas, bastante más grande que la RAM. Esto fuerza lecturas reales a disco. - Carga:
UPDATEaleatorios, 64 clientes, 16 threads de pgbench, 5 minutos. - Lado de red: un volumen SSD de propósito general con 3.000 IOPS aprovisionados (la línea base).
- Latencia por transacción: 4,0 ms en NVMe contra 36,9 ms en disco de red.
- Mantenimiento: un VACUUM sobre 10 GB de bloat tardó 366 segundos en NVMe y 964 en red. Drenar 10 GB de backlog de replicación lógica llevó 139 segundos contra 238.
¿Por qué un disco de red frena tanto a Postgres?
Porque cada lectura de página que no está en shared_buffers y cada fsync del WAL en el commit pagan la latencia del disco, y el disco de red suma un salto por la red. El artículo ampliado de ClickHouse ubica el SSD de red en 1 a 10 ms por operación y el NVMe local en decenas de microsegundos.
El desglose del recap muestra dónde se van los milisegundos de cada transacción:
| Componente | Disco de red | NVMe local |
|---|---|---|
| Lectura de páginas | ~19 ms | 0,3 ms |
| fsync del WAL al commit | ~11 ms | 1,5 ms |
| Locks / scheduler | ~5 ms | 0,2 ms |
| Trabajo de CPU | ~2 ms | ~2 ms |
La CPU hace el mismo trabajo en ambos casos. Lo que cambia es el tiempo que los backends pasan esperando. En una foto de pg_stat_activity a mitad de la corrida, 29 de 64 backends (cerca del 45%) esperaban IO:DataFileRead en el disco de red, contra 9 (cerca del 14%) en NVMe. En un perfil de 240 segundos, el lado NVMe consumió 2.253 CPU-segundos (unos 9,4 cores) y el lado de red apenas 251 (alrededor de 1 core). El servidor de red no estaba saturado: estaba bloqueado.
El recap lo resume así: la mayor parte de la latencia extra del disco de red vino de esperar al almacenamiento, no de que PostgreSQL hiciera más trabajo de CPU.
¿Es un benchmark confiable o es marketing?
Es un dato útil con sesgo declarado: ClickHouse vende un Postgres administrado sobre NVMe, y el resultado favorece su tesis. Los números son plausibles dado el orden de magnitud de las latencias, pero el 9,24× no se traslada a cualquier carga ni a cualquier configuración de disco de red.
- Lado de red en su piso: los propios autores aclaran que el volumen usó la línea base de 3.000 IOPS y que otra configuración "would most likely produce different results". Un volumen con más IOPS aprovisionados achicaría la brecha, aunque no la latencia por operación.
- Carga extrema para el caso:
UPDATEaleatorios sobre una tabla de 482 GiB con 16 GiB de buffers es casi el peor escenario para un disco lento. Si tu working set entra en RAM, el efecto será mucho menor. - Reproducibilidad limitada en el recap: el resumen no incluye código ni archivos de configuración para repetir la prueba, así que conviene tomarlo como orden de magnitud y no como número a prometer.
¿Qué se pierde al pasar a NVMe local?
Se pierde la durabilidad "gratis" del disco de red: el NVMe local suele estar atado a la vida de la máquina, no tiene el modelo de snapshots de un volumen de bloque y su capacidad depende del tamaño del servidor. Si el host muere, los datos pueden morir con él. Hay que compensarlo con replicación y archivado de WAL.
El artículo de ClickHouse propone dos piezas, que son prácticas estándar de Postgres y no algo exclusivo de su producto:
- Replicación sincrónica por quórum: por ejemplo
synchronous_standby_names = 'ANY 1 (standby1, standby2)', con las réplicas en zonas distintas. Cada commit espera confirmación de al menos una réplica. - Archivado continuo de WAL a almacenamiento de objetos: el artículo menciona WAL-G, con un RPO de segundos.
- Failover automatizado: con herramientas como Patroni o repmgr.
Esto es operación que antes delegabas al volumen de red. La latencia mejora, pero ahora la resiliencia es tuya. Para ampliar sobre mantenimiento, tenemos notas sobre Autovacuum y sobre PostgreSQL 19 antes del RC1 en este mismo blog.
¿Cómo saber si tu Postgres está limitado por el almacenamiento?
Mirá los wait events de las sesiones activas mientras la carga es real. Si DataFileRead, WALSync o WALWrite dominan la lista, estás esperando al disco. Si dominan Lock o directamente no hay esperas y la CPU está alta, el problema está en otro lado.
Una consulta rápida, repetida varias veces durante un pico:
SELECT wait_event_type, wait_event, count(*)
FROM pg_stat_activity
WHERE state = 'active'
GROUP BY 1, 2
ORDER BY 3 DESC;Después medí el disco por separado, en una ventana de mantenimiento o en una réplica, con la misma ruta de datos que usa Postgres. Latencia de commit (fsync) con la herramienta que trae Postgres:
pg_test_fsync -f /var/lib/postgresql/fsync.testY lecturas aleatorias de 8 KB (el tamaño de página de Postgres) con fio:
fio --name=randread --filename=/var/lib/postgresql/fio.test \
--size=4G --rw=randread --bs=8k --iodepth=32 \
--ioengine=libaio --direct=1 --runtime=60 --time_based \
--group_reporting- Mirá la latencia, no solo los IOPS: comparar el p99 de
fiocon la regla de 1 a 10 ms (red) contra decenas de microsegundos (NVMe) te dice en qué mundo estás. - Activá
track_io_timing: en versiones recientes conpg_stat_iopodés ver tiempos de lectura y escritura por tipo de backend. Verificá la disponibilidad en la documentación de tu versión. - Reproducí con pgbench: armá un dataset mayor que la RAM y corré una carga parecida a la tuya antes de sacar conclusiones.
¿Cuándo conviene NVMe local y cuándo no?
Conviene cuando tu carga es de escritura intensiva o con lecturas aleatorias sobre un dataset que no entra en RAM, y tenés (o querés armar) replicación y backups propios. No conviene cuando tu base es chica, cabe en memoria, o necesitás snapshots y redimensionado simples sin operar un clúster.
- Sí, evaluá NVMe local: OLTP con muchos
UPDATE, tablas de cientos de GB,VACUUMy replicación lógica que no llegan a tiempo, y wait events dominados por I/O. - Probablemente no hace falta: bases que caben en
shared_buffersmás page cache, cargas mayormente de lectura cacheada, o equipos sin capacidad para operar failover. - Primero lo barato: revisá índices, planes de ejecución y autovacuum. Si eso está mal, el mejor disco solo lo maquilla.
- Al contratar un VPS o servidor: preguntá si el disco es local o de red, de qué tipo (NVMe, SATA SSD) y qué IOPS y latencia garantiza. Un servidor dedicado o un plan cloud con NVMe local cambia la ecuación; verificalo en la ficha técnica del plan, no por el nombre comercial.
Preguntas frecuentes
¿Cuántos TPS más rinde Postgres en NVMe local que en disco de red?
En el benchmark de ClickHouse rindió 9,24 veces más: 16.030 TPS contra 1.734 TPS (medianas). Es el resultado de una carga de escritura aleatoria sobre una tabla de 482 GiB, así que tu diferencia real puede ser bastante menor.
¿Cuánta latencia por transacción mostró cada tipo de disco?
4,0 ms en NVMe local y 36,9 ms en el disco de red, según el recap del talk. La mayor parte de la diferencia vino de la lectura de páginas y del fsync del WAL.
¿El NVMe local pierde los datos si cae el servidor?
Puede perderlos si dependés de un único nodo, porque el NVMe local suele estar atado a la vida de la máquina. Por eso el artículo propone réplicas sincrónicas por quórum y archivado continuo de WAL.
¿Hace falta cambiar la configuración de Postgres para aprovechar el NVMe?
Probablemente convenga revisar parámetros ligados al costo de I/O, como random_page_cost y la concurrencia de I/O, pero los valores correctos dependen de tu versión y tu carga. Medí antes y después en lugar de copiar números de un post.
¿Es el disco el cuello de botella más común en Postgres?
No necesariamente: los síntomas de lentitud pueden tener causas distintas. Los wait events de pg_stat_activity te dicen cuál es el tuyo.
Conclusión
El mensaje útil no es "migrá todo a NVMe", sino "medí a qué esperan tus backends". Si la mayoría espera I/O, un disco con latencia de microsegundos puede valer más que otra vuelta de tuning. Si no, ahorrate el proyecto. Y si vas a comparar el 9,24× contra tu realidad, tené presente que lo publicó un proveedor con producto propio, sobre una configuración de disco de red en su piso.
Fuentes: recap del talk de POSETTE 2026 y Postgres on NVMe (ClickHouse).