Este artículo responde a una pregunta específica (cómo comparar una API backend de forma reproducible) documentando el protocolo que aplicaremos en Aurabase antes de publicar cualquier cifra de rendimiento. No resultados: un método. Cualquier medición ya publicada en otra parte de este sitio (especialmente en nuestra página Rendimiento) que aún no se base en este protocolo debe tratarse como no verificada hasta nuevo aviso.
Lo esencial
Hasta la fecha, no existen resultados de rendimiento de Aurabase siguiendo un protocolo publicado y reproducible; este artículo documenta la metodología que aplicaremos para producirlos, no los resultados ya obtenidos. El repositorio ya contiene un conjunto de pruebas de 3 niveles: micro-benchmarks de Criterion.rs en 3 cajas, pruebas de carga k6 en 8 escenarios HTTP/WebSocket y un script de Python para una comparación directa entre Postgres y API con cálculo de percentiles. El protocolo completo (duración de la medición, percentiles en lugar de promedios, aislamiento del entorno, divulgación de versión y fecha) se basa en fuentes externas verificadas: PostgreSQL, Criterion.rs, k6 (Grafana), HdrHistogram, PlanetScale y Convex. Cualquier afirmación de rendimiento ya publicada en otra parte de este sitio sin que se relacione con este protocolo debe considerarse no verificada.
¿Por qué no publicamos cifras desnudas?
Convex, editor de un backend responsivo de la competencia, se ha distanciado públicamente de lo que su equipo técnico llama la “guerra de gráficos de barras” entre proveedores de bases de datos. Su fórmula es directa: “Se trata de escalar el teatro, no escalar”: escalar el teatro, no un escalamiento real (stack.convex.dev/on-competitive-benchmarks, blog técnico de Stack, consultado el 23 de agosto de 2026).
Su argumento central: un punto de referencia que compara dos sistemas con diferentes garantías de coherencia, topología o modelo de precios a menudo no prueba lo mismo, incluso cuando afirma hacerlo: "el punto de referencia en realidad no está probando lo mismo". Este reflejo tiene un nombre en la industria: benchmarketing, publicando una cifra elegida por su efecto de marketing más que por su rigor metodológico.
Nuestra respuesta no es negarnos a medir: negarnos a publicar una cifra indefinidamente sería tan deshonesto como publicar una cifra sin fundamento. Se trata de documentar primero cómo mediríamos, con qué herramientas y bajo qué condiciones, antes de afirmar haber medido algo. Esto también es lo que distingue una comparación útil (como nuestra comparación Aurabase vs Appwrite, que documenta diferencias arquitectónicas verificables) de una comparación de cifras de rendimiento sin un protocolo común.
Esto es particularmente importante para un líder técnico o un CTO que debe defender una elección de backend en un comité técnico: una cifra que no puede atribuirse a un método no sobrevive a la primera pregunta, algo insistente. Un protocolo documentado se defiende por sí solo: puede mostrar el script, la versión probada y ejecutar la prueba nuevamente frente a alguien si es necesario.
Lo que hace que la mayoría de los benchmarks de backend sean engañosos
Surgen sistemáticamente dos errores: comparar diferentes topologías sin informarlo y medir la latencia de una manera que oculte exactamente las pausas que más le importan al usuario.
En el primer punto, PlanetScale documenta explícitamente su restricción de paridad de hardware: cada entorno comparado debe ejecutarse en recursos informáticos (vCPU, RAM) iguales o mayores que la instancia de referencia, en la misma región de la nube (planetscale.com/benchmarks, metodología “Telescope”, consultada el 23 de agosto de 2026). Sin esta disciplina, una brecha de latencia puede simplemente reflejar una máquina más grande, no una arquitectura más rápida.
El mismo principio se aplica al estado de la caché y a la topología de la red. Una instancia que acaba de iniciarse (caché de Postgres inactivo, grupo de conexiones vacío, plan de consultas aún no almacenado en caché) responde estructuralmente más lentamente que una instancia que se ha estado ejecutando durante una hora con una carga estable. Una consulta de la misma región que la base de datos responde estructuralmente más rápido que una consulta entre regiones. Dos puntos de referencia que no especifican ninguno de los dos simplemente no son comparables, incluso si muestran unidades idénticas.
En el segundo punto, la trampa se llama omisión coordinada. HdrHistogram, el proyecto de referencia sobre medición de latencia creado por Gil Tene, lo explica de esta manera: cuando un generador de carga espera la respuesta de una solicitud antes de enviar la siguiente (bucle cerrado), una pausa del servicio reduce automáticamente la cantidad de solicitudes enviadas durante la pausa y, por lo tanto, la cantidad de mediciones de alta latencia registradas (github.com/HdrHistogram/HdrHistogram, consultado el 23 de agosto de 2026). El proyecto ofrece un ejemplo concreto y cuantificado: en un sistema hipotético que muestrea su latencia cada 10 ms durante 200 segundos, una sola pausa de 100 segundos en mitad de la prueba es suficiente para producir, sin corrección, un histograma en el que aproximadamente el 99,99% de las respuestas parecen encajar en menos de 1 ms, aunque en esta única pausa haya transcurrido la mitad del tiempo real.
Una prueba de carga de circuito cerrado que solo envía una solicitud después de recibir la respuesta anterior sistemáticamente no representa pausas largas. El p99 que muestra puede ser mejor que la realidad experimentada por un usuario real, no porque el sistema sea rápido, sino porque el protocolo de medición "olvidó" enviar las consultas mientras estaba en pausa.
Por qué miente el promedio: p50, p95, p99
Una latencia promedio puede parecer excelente cuando una de cada veinte solicitudes tarda cinco veces más. Esto es precisamente lo que revelan los percentiles y lo que el promedio oculta estructuralmente.
Mecánicamente, un percentil no tiene nada de misterioso: ordenar todas las latencias medidas en orden ascendente y luego tomar el valor en la posición correspondiente. De 1000 consultas ordenadas, p50 es el valor 500, p95 el 950, p99 el 990. Una sola solicitud anormalmente lenta entre 1000 es suficiente para hacer que el p99 se mueva; es precisamente su sensibilidad a casos raros lo que lo hace útil, donde esta misma solicitud aislada casi no tiene efecto en el promedio.
Signo revelador: el informe de texto que pgbench, la herramienta de referencia oficial de PostgreSQL, muestra de forma predeterminada proporciona un promedio y una desviación estándar , no percentiles (postgresql.org/docs/current/pgbench.html, consultado el 23 de agosto de 2026). Su documentación oficial también advierte: “Nunca creas en una prueba que se ejecute solo durante unos segundos”; nunca creas en una prueba que solo se ejecute durante unos segundos, lo cual se aplica tanto a la duración como a la métrica elegida.
k6, la herramienta de carga que utilizamos para el nivel 2 de nuestra suite, resuelve esto con umbrales expresados en percentiles: la sintaxis p(95)<500 define un criterio de aprobación/rechazo (el 95% de las solicitudes deben responder dentro de 500 ms) directamente en la configuración de prueba (grafana.com/docs/k6, consultado el 23 de agosto de 2026).
| p50 (mediana) | La mitad de las consultas son más rápidas que este valor. | Oculta completamente la cola de distribución. |
|---|---|---|
| p95 | 1 de cada 20 consultas es más lenta | Zona donde aparecen los primeros usuarios insatisfechos |
| p99 | 1 de cada 100 consultas es más lenta | Más sensible a la omisión coordinada si el protocolo está mal diseñado |
Los 3 niveles de referencia ya presentes en nuestro repositorio
Publicar una metodología sin herramientas reales sería una forma más de teatro. La carpeta benchmarks/ en el repositorio de Aurabase ya contiene una suite de 3 niveles, inspirada en su estructura en la metodología pública Supabase: las herramientas existen, los resultados medidos y fechados aún no existen.
Nivel 1: Micro-benchmarks Criterion.rs
Tres cajas del espacio de trabajo de carga tienen puntos de referencia vinculados a la CPU: aura-crypto (hash Argon2, JWT HS256 - generación, validación y firma para PostgREST, cifrado AES-GCM), aura-db-adapters (filtros de análisis y select en formato PostgREST - eq., gte., in.(), relación incrustada) y aura-core (serialización JSON, resolución schema_name, validación UUID).
aura-db-adapters mide específicamente el costo de analizar consultas en formato PostgREST: cuatro casos para filtros (simple_4, complex_10, or_group, in_large_50 con 50 valores) y cuatro para select (columnas individuales, *, una relación incrustada, cinco incrustaciones). Este es el tipo de costo invisible en una prueba de carga global: una regresión en el análisis de un filtro or.(...) complejo no cambiaría casi nada en el p95 de un punto final poco utilizado, pero sería mensurable en un punto final con mucho tráfico; de ahí el interés en aislarlo en un micro-benchmark en lugar de depender únicamente del nivel 2.
aura-core adopta un enfoque diferente: en lugar de medir el tiempo sin procesar, mide el rendimiento de (Throughput::Bytes) en la serialización JSON y deserialización de mensajes internos NatsRequest/NatsResponse intercambiados entre la puerta de enlace y los servicios, con tres tamaños de carga útil realistas (una solicitud mínima, una solicitud con un cuerpo JSON anidado, una respuesta de lista de 50 líneas).
Criterion.rs no se limita a cronometrar un bucle. Primero ejecuta una fase de calentamiento para llenar los cachés de CPU/OS, detecta valores atípicos con una versión modificada del método de Tukey (sin excluirlos del conjunto de datos), calcula intervalos de confianza mediante arranque en una gran cantidad de muestras remuestreadas y detecta regresiones de rendimiento entre dos ejecuciones mediante la prueba estadística de Student, con un umbral de ruido configurable (generalmente ±1%) para ignorar variaciones que no son estadísticamente significativas (bheisler.github.io/criterion.rs/book/analysis.html, consultado el 23 de agosto de 2026).
Cada ejecución de Criterion genera un informe HTML detallado en target/criterion/: distribuciones, gráficos de regresión y comparación con la ejecución anterior. Es esta relación, no sólo una línea terminal, la que una metodología seria debe permitir regenerar.
Nivel 2: prueba de carga k6
Ocho scripts k6 cubren la puerta de enlace en el lado del plano de datos: health (línea base de latencia), auth-flow (registro → inicio de sesión → actualización → cierre de sesión), crud-read y crud-write, storage (carga/descarga), realtime-ws, breakpoint (aumento de carga hasta falla) y supabase-compare. Siete están conectados a un objetivo Makefile dedicado: supabase-compare.js existe en el repositorio pero aún no tiene un objetivo, una situación que este artículo documenta tal como está en lugar de disfrazarla.
La configuración compartida define umbrales por tipo de operación. Estos son criterios de aprobación/rechazo que la prueba verifica cada vez que se ejecuta, no resultados ya medidos:
| Lectura (OBTENER) | p95 < 500 ms · p99 < 1000 ms | Configurar k6 (benchmarks/k6/lib/config.js) |
|---|---|---|
| Escritura (POST/PARCHE) | p95 < 300 ms · p99 < 1000 ms | Configurar k6 |
| Autenticación (iniciar sesión/actualizar) | p95 < 300 ms · p99 < 1000 ms | Configurar k6 |
| Almacenamiento (carga/descarga) | p95 < 500 ms · p99 < 2000 ms | Configurar k6 |
| Tasa de error, todos los escenarios | < 1 % | Configurar k6 |
El README.md en la carpeta benchmarks/ documenta un umbral de lectura de p95 en < 200ms ("Supabase SLO"), mientras que el umbral realmente aplicado en benchmarks/k6/lib/config.js, el que ejecuta la prueba, es p(95)<500. Los dos archivos se derivan uno del otro. Este es un ejemplo concreto, encontrado al leer el código fuente de este artículo, de por qué un protocolo debería tener una única fuente de verdad versionada en lugar de estar documentada en dos lugares: sin ella, incluso un equipo que intenta ser riguroso termina publicando umbrales contradictorios.
Nivel 3: comparación directa entre PostgreSQL y API
Un script de Python (direct_vs_api.py) mide la sobrecarga real de la puerta de enlace + capa de servicio comparando solicitudes psycopg2 directas con llamadas HTTP en la misma operación: lista, lectura única por identificación, lectura filtrada y ordenada. Cada medición sigue un calentamiento de 10 iteraciones antes del ciclo cronometrado, luego calcula el promedio, p50, p95, p99 y un rendimiento en operaciones por segundo.
Un segundo script (aurabase_vs_supabase.py) aplica la misma lógica de calentamiento y cálculo de percentiles a una comparación directa con una instancia local de Supabase (Supabase CLI, localhost:54321 de forma predeterminada): la misma máquina, la misma red local para ambos, exactamente la disciplina de paridad de entorno que PlanetScale documenta para sus propias comparaciones.
Un script de orquestación (collect_baseline.sh, destino bench-baseline de Makefile) conecta los tres niveles: Criterion en las 3 cajas, un subconjunto de los escenarios k6 (health y crud-read hoy, no los 8 todavía), luego la comparación de Python, y escribe registros, informes JSON y Criterion HTML en una carpeta con marca de tiempo única: benchmarks/results/AAAAMMJJ_HHMMSS/. Éste es exactamente el reflejo de la divulgación fechada, en una sola tirada reproducible, que la siguiente sección formaliza en un protocolo completo.
El protocolo que aplicaremos antes de publicar una figura
Ocho compromisos, cada uno de ellos anclado en una práctica ya documentada por una herramienta o proyecto de terceros reconocido, no inventado para la ocasión.
- Precalentamiento separado de la medición. Criterion.rs llena los cachés de CPU/OS antes de cronometrar;
pgbenchrecomienda explícitamente no creer nunca en una carrera que dura sólo unos segundos. - Duración fija, no un número fijo de iteraciones. Una carga necesita tiempo para converger; esta es la función de
stagesk6 y el indicador-Tdepgbench. - Percentiles, nunca solo el promedio, y vigilancia activa en caso de omisión coordinada si el generador de carga opera en un circuito cerrado.
- Entorno documentado en detalle: git commit del servicio probado, versión de PostgreSQL, especificación de hardware, versión de la herramienta de carga. PlanetScale documenta sus parámetros TPCC exactos (
TABLES=20,SCALE=250, ~500 GB) precisamente por esta razón: sin estos detalles, nadie puede reproducir una ejecución. - Resultados versionados y con marca de tiempo, nunca un solo número grabado en una página de marketing sin fecha. Las herramientas actuales ya están escritas en un archivo fechado; Será necesario extender este reflejo a cualquier medición publicada públicamente, con la región anfitriona documentada como cualquier otra variable ambiental (consulte nuestra guía sobre Soberanía de acogida de la UE, relevante en cuanto una cifra depende de una región determinada).
- Guiones y datos sin procesar publicados junto con el resultado agregado, no solo un promedio final. PlanetScale incluso invita a los lectores a informar de un error metodológico en una dirección específica: una postura que consideramos saludable y que queremos retomar.
- Rendimiento anunciado junto con la latencia, no solo uno u otro. Un sistema puede tener una latencia excelente con carga baja y colapsar en el rendimiento a medida que aumenta la concurrencia; eso es exactamente lo que el escenario
breakpoint(escalar hasta fallar) de nuestra suite k6 está diseñado para revelar, y lo que la medición de microbenchmarkThroughput::Bytesde Criterion captura a nivel de función. - Brecha importante antes de anunciar una mejora. Una variación de un pequeño porcentaje entre dos ejecuciones puede ser ruido de medición en lugar de una ganancia real: Criterion.rs calcula la probabilidad de que la diferencia observada se deba al azar antes de calificarla como regresión o mejora. Una cifra aislada, sin esta verificación, es sólo una anécdota estadística.
lo que no haremos
Esta lista cuenta tanto como el protocolo positivo anterior.
- Comparar diferentes topologías (instancia autohospedada versus administrada, instancia fría versus precalentada) sin informarlo explícitamente.
- Conservar la mejor racha de diez sin mencionar los otros nueve.
- Publicar una figura sin fecha, sin versión de servicio, sin guion de reproducción.
- Volver a publicar una figura de marketing existente siempre que no se remonta a este protocolo.
- Compararnos con un competidor basándose en una cifra bruta de rendimiento si ese competidor no publica su propia metodología de manera equivalente: una cifra versus silencio no es una comparación, es un eslogan.
Se distribuyó una cifra como “arranque en frío en menos de 1 ms” sin estar respaldada por un punto de referencia reproducible. Ahora se trata internamente como no compatible y no debe leerse como una característica medida del producto hasta que cualquier medición fechada, con metodología publicada, lo confirme. Este es precisamente el tipo de afirmación que este protocolo pretende evitar que se repita.
El protocolo mínimo para comparar cualquier backend
Este protocolo no depende de ninguna herramienta específica de Aurabase; puede aplicarlo a su propia API hoy.
- Establezca la carga antes de la herramienta: solo lectura, escritura, combinación realista para su aplicación, no una proporción genérica copiada de otro proyecto.
- Separe explícitamente la fase de precalentamiento de la fase de medición.
- Realice la prueba durante el tiempo suficiente: minutos, no segundos.
- Medir en percentiles (p50/p95/p99), nunca en promedio solo.
- Verifique que su generador de carga no esté en circuito cerrado, o corrija la omisión de coordinación en el análisis.
- Aísle el entorno bajo prueba: sin vecinos ruidosos ni tareas en segundo plano que compitan entre sí.
- Publique la versión probada, la fecha, las especificaciones de hardware y el script, no solo el resultado final.
En una base básica de Postgres, este protocolo requiere un comando pgbench: 20 clientes simultáneos distribuidos en 4 subprocesos, durante 5 minutos, con un informe de progreso cada 10 segundos:
Herramientas de referencia, por nivel
Cinco herramientas, cada una adaptada a un nivel diferente de la pila; ninguna reemplaza a las demás.
| Micrófono (función) | Criterio.rs | CPU pura, estadísticas de arranque |
|---|---|---|
| consulta SQL | banco de pgb | Transacción tipo TPC-B, tps y latencia |
| Carga HTTP/WS | k6 (Grafana) | Percentiles, umbrales de aprobación/reprobación |
| OLTP a escala | sysbench + TPCC (Metodología del telescopio) | QPS, coste por rendimiento |
| Corrección de medición | HdrHistograma | Compensa la omisión coordinada |