PRODPiattaforma BaaS europea sovranaApri Dashboard →

Prestazioni · 15 lettura minima

Come confrontiamo un backend: una metodologia ripetibile

Affane Daylami · Fondateur · 8 luglio 2026

Torniamo al blog

Una cifra di riferimento senza un metodo non dimostra nulla. "p95 sotto X ms", "avvio a freddo inferiore a Y ms": chiunque può scriverlo su una pagina di marketing. Ciò che dimostra qualcosa è il metodo: l'attrezzatura utilizzata, la durata del test, il protocollo di misurazione e la possibilità per terzi di riprodurlo identico.

Questo testo inglese è stato generato automaticamente dall'originale francese e non è stato ancora rivisto.
Questa pagina è stata tradotta automaticamente. Fa fede la versione inglese.

Questo articolo risponde a una domanda specifica: come valutare un'API backend in modo riproducibile, documentando il protocollo che applicheremo in Aurabase prima di pubblicare qualsiasi dato sulle prestazioni. Non risultati: un metodo. Qualsiasi misurazione già pubblicata altrove su questo sito (in particolare sulla nostra pagina Performance) che non si basa già su questo protocollo deve essere trattata come non verificata fino a nuovo avviso.

L'essenziale

Ad oggi non esistono risultati sulle prestazioni di Aurabase a seguito di un protocollo pubblicato e riproducibile: questo articolo documenta la metodologia che applicheremo per produrli, non i risultati già ottenuti. Il repository contiene già una suite di test a 3 livelli: micro-benchmark Criterion.rs su 3 crate, test di carico k6 su 8 scenari HTTP/WebSocket e uno script Python per il confronto diretto Postgres vs API con calcolo percentile. Il protocollo completo (durata della misurazione, percentili anziché medie, isolamento dell'ambiente, divulgazione di versione e data) si basa su fonti esterne verificate: PostgreSQL, Criterion.rs, k6 (Grafana), HdrHistogram, PlanetScale e Convex. Qualsiasi affermazione sulle prestazioni già pubblicata altrove su questo sito senza essere ricondotta a questo protocollo deve essere considerata non verificata.

#
Posizione editoriale

Perché non pubblichiamo cifre nude

Convex, editore di un backend reattivo concorrente, ha preso pubblicamente le distanze da quella che il suo team tecnico chiama la "guerra dei grafici a barre" tra i fornitori di database. La sua formula è diretta: "È ridimensionamento del teatro, non ridimensionamento" - ridimensionamento del teatro, non reale ridimensionamento (stack.convex.dev/on-competitive-benchmarks, blog tecnico Stack, accesso il 23 agosto 2026).

Il suo argomento centrale: un benchmark che confronta due sistemi con diverse garanzie di coerenza, topologia o modello di prezzo spesso non testa la stessa cosa, anche quando afferma di farlo: “il benchmark in realtà non sta testando la stessa cosa”. Questa reflex ha un nome nel settore: benchmarketing, pubblicando una figura scelta per il suo effetto di marketing più che per il suo rigore metodologico.

La nostra risposta non è quella di rifiutarci di misurare: rifiutare di pubblicare un dato a tempo indeterminato sarebbe altrettanto disonesto quanto pubblicarne uno non comprovato. Si tratta di documentare innanzitutto come misureremmo, con quali strumenti e in quali condizioni, prima di affermare di aver misurato qualcosa. Questo è anche ciò che distingue un confronto utile (come il nostro Confronto Aurabase vs Appwrite, che documenta differenze architetturali verificabili) da un confronto di dati prestazionali senza un protocollo comune.

Ciò è particolarmente importante per un lead tecnico o un CTO che deve difendere una scelta di backend in un comitato tecnico: una figura non riconducibile a un metodo non sopravvive alla prima, un po' insistente, domanda. Un protocollo documentato è autodifesa: puoi mostrare lo script, la versione testata ed eseguire nuovamente il test davanti a qualcuno, se necessario.

#
Diagnosi

Ciò che rende fuorviante la maggior parte dei benchmark di backend

Due trappole emergono sistematicamente: confrontare diverse topologie senza segnalarle e misurare la latenza in un modo che nasconda esattamente le pause che contano di più per l'utente.

Sul primo punto, PlanetScale documenta esplicitamente il suo vincolo di parità hardware: ogni ambiente confrontato deve funzionare con risorse di calcolo (vCPU, RAM) uguali o superiori all'istanza di riferimento, nella stessa regione cloud (planetscale.com/benchmarks, metodologia “Telescope”, accesso il 23 agosto 2026). Senza questa disciplina, un divario di latenza potrebbe semplicemente riflettere una macchina più grande, non un’architettura più veloce.

Lo stesso principio si applica allo stato della cache e alla topologia della rete. Un'istanza appena avviata (cache Postgres fredda, pool di connessioni vuoto, piano di query non ancora memorizzato nella cache) risponde strutturalmente più lentamente di un'istanza in esecuzione per un'ora con carico stabile. Una query dalla stessa regione del database risponde strutturalmente più velocemente di una query tra regioni. Due benchmark che non specificano nessuno dei due semplicemente non sono comparabili, anche se mostrano unità identiche.

Sul secondo punto, la trappola si chiama omissione coordinata. HdrHistogram, il progetto di riferimento sulla misurazione della latenza creato da Gil Tene, lo spiega in questo modo: quando un generatore di carico attende la risposta di una richiesta prima di inviare quella successiva (anello chiuso), una pausa del servizio elimina automaticamente il numero di richieste inviate durante la pausa — e quindi il numero di misurazioni ad alta latenza registrate (github.com/HdrHistogram/HdrHistogram, accesso il 23 agosto 2026). Il progetto fornisce un esempio concreto e quantificato: su un ipotetico sistema che campiona la sua latenza ogni 10 ms per 200 secondi, una singola pausa di 100 secondi nel mezzo del test è sufficiente per produrre, senza correzione, un istogramma in cui circa il 99,99% delle risposte sembra rientrare sotto 1 ms - anche se metà del tempo reale è trascorso in questa singola pausa.

Trappola classica

Un test di carico a circuito chiuso che invia una richiesta solo dopo aver ricevuto la risposta precedente sottorappresenta sistematicamente lunghe pause. Il p99 visualizzato potrebbe essere migliore della realtà vissuta da un utente reale, non perché il sistema sia veloce, ma perché il protocollo di misurazione si è "dimenticato" di inviare le query mentre era in pausa.

#
Statistiche

Perché la media mente: p50, p95, p99

Una latenza media può sembrare eccellente quando una richiesta su venti impiega cinque volte il tempo. Questo è esattamente ciò che i percentili rivelano e ciò che la media strutturalmente nasconde.

Meccanicamente non c'è nulla di misterioso in un percentile: ordina tutte le latenze misurate in ordine crescente, quindi prendi il valore nella posizione corrispondente. Su 1000 query ordinate, p50 è il 500esimo valore, p95 il 950esimo, p99 il 990esimo. È sufficiente una sola richiesta anormalmente lenta su 1000 per far muovere il p99: è proprio la sua sensibilità a casi rari che lo rende utile, dove questa stessa richiesta isolata non ha quasi alcun effetto sulla media.

Segno rivelatore: il rapporto testuale che pgbench, lo strumento di benchmark ufficiale di PostgreSQL, visualizza per impostazione predefinita fornisce una media e una deviazione standard , non percentili (postgresql.org/docs/current/pgbench.html, accesso il 23 agosto 2026). La sua documentazione ufficiale avverte inoltre: “Non credere mai a nessun test che dura solo pochi secondi” – non credere mai a un test che dura solo pochi secondi, il che si applica tanto alla durata quanto alla metrica scelta.

k6, lo strumento di caricamento che utilizziamo per il livello 2 della nostra suite, risolve questo problema con soglie espresse in percentile: la sintassi p(95)<500 definisce un criterio pass/fail — il 95% delle richieste deve rispondere entro 500 ms — direttamente nella configurazione di test (grafana.com/docs/k6, consultato il 23 agosto 2026).

p50 (mediana)La metà delle query sono più veloci di questo valoreNasconde completamente la coda di distribuzione
p951 query su 20 è più lentaArea dove compaiono i primi utenti insoddisfatti
p991 query su 100 è più lentaPiù sensibile all'omissione coordinata se il protocollo è mal progettato
#
Codice registrato

I 3 livelli di benchmark già presenti nel nostro repository

Pubblicare una metodologia senza strumenti reali sarebbe solo un’altra forma di teatro. La cartella benchmarks/ nel repository Aurabase contiene già una suite a 3 livelli, ispirata nella sua struttura alla metodologia pubblica Supabase: gli strumenti esistono, i risultati misurati e datati non esistono ancora.

3
LIVELLI DI PROVA
Micro, carico HTTP, confronto
3
CASSE BENCHMARK
aura-crypto, adattatori aura-db, aura-core
8
SCRIPT K6
7 collegati a Makefile, 1 in attesa

Livello 1 — Criterio dei micro-benchmark.rs

Tre crate dell'area di lavoro Cargo hanno benchmark dedicati legati alla CPU: aura-crypto (hash Argon2, JWT HS256 — generazione, convalida e firma per PostgREST, crittografia AES-GCM), aura-db-adapters (filtri di analisi e select in formato PostgREST — eq., gte., in.(), incorporamenti di relazioni) e aura-core (serializzazione JSON, risoluzione schema_name, convalida UUID).

libs/aura-crypto/benches/crypto_bench.rsrust
// Estratto effettivo dal repository
let mut group = c.benchmark_group("jwt/hs256");

group.bench_function("generate", |b| {
    b.iter(|| jwt::generate_access_token(
        black_box(user_id), black_box(project_id),
        black_box("authenticated"), black_box(SECRET),
    ))
});

group.bench_function("validate", |b| {
    b.iter(|| jwt::validate_token(black_box(&token), black_box(SECRET)))
});

aura-db-adapters misura specificamente il costo dell'analisi delle query in formato PostgREST: quattro casi per i filtri (simple_4, complex_10, or_group, in_large_50 con 50 valori) e quattro per select (colonne singole, *, un incorporamento di relazione, cinque incorporamenti). Questo è il tipo di costo invisibile in un test di carico globale: una regressione sull'analisi di un filtro complesso or.(...) non cambierebbe quasi nulla nel p95 di un endpoint poco utilizzato, ma diventerebbe misurabile su un endpoint con traffico elevato - da qui l'interesse a isolarlo in un micro-benchmark piuttosto che fare affidamento esclusivamente sul livello 2.

aura-core adotta un approccio diverso: invece di misurare il tempo grezzo, misura il throughput (Throughput::Bytes) sulla serializzazione e deserializzazione JSON dei messaggi interni NatsRequest/NatsResponse scambiati tra il gateway e i servizi — con tre dimensioni realistiche del payload (una richiesta minima, una richiesta con un corpo JSON nidificato, un risposta all'elenco).

libs/aura-core/benches/core_bench.rsrust
group.throughput(Throughput::Bytes(
    serde_json::to_vec(&small).unwrap().len() as u64
));
group.bench_function("NatsRequest/small", |b| {
    b.iter(|| serde_json::to_vec(black_box(&small)).unwrap())
});

Criterion.rs non si limita a cronometrare un ciclo. Innanzitutto esegue una fase di riscaldamento per riempire le cache della CPU/sistema operativo, rileva i valori anomali con una versione modificata del metodo di Tukey (senza escluderli dal set di dati), calcola gli intervalli di confidenza eseguendo il bootstrap su un numero elevato di campioni ricampionati e rileva le regressioni delle prestazioni tra due esecuzioni mediante il test statistico di Student, con una soglia di rumore configurabile, in genere ±1%, per ignorare le variazioni che non sono statisticamente significative (bheisler.github.io/criterion.rs/book/analysis.html, accesso il 23 agosto 2026).

Localmente riproducibile

Ogni esecuzione di Criterion genera un report HTML dettagliato in target/criterion/: distribuzioni, grafici di regressione, confronto con l'esecuzione precedente. È questa relazione, non solo un filo terminale, che una metodologia seria deve consentire di rigenerare.

Livello 2: test di carico k6

Otto script k6 coprono il gateway sul lato del piano dati: health (base di latenza), auth-flow (registrazione → login → aggiornamento → logout), crud-read e crud-write, storage (caricamento/download), realtime-ws, breakpoint (aumento del carico fino al guasto) e supabase-compare. Sette sono collegati a un target Makefile dedicato: supabase-compare.js esiste nel repository ma non ha ancora un target, uno stato di cose che questo articolo documenta così com'è anziché mascherarlo.

benchmarks/k6/scenarios/crud-read.jsjavascript
export const options = {
  scenarios: {
    crud_read: {
      executor: 'ramping-vus',
      startVUs: 10,
      stages: [
        { duration: '30s', target: 50 },
        { duration: '1m', target: 200 },
        { duration: '30s', target: 0 },
      ],
    },
  },
  thresholds: THRESHOLDS_READ,
}

La configurazione condivisa definisce le soglie per tipo di operazione. Questi sono i criteri di superamento/fallimento che il test verifica ogni volta che viene eseguito, non i risultati già misurati:

Lettura (OTTIENI)p95 < 500 ms · p99 < 1000 msConfigurazione k6 (benchmarks/k6/lib/config.js)
Scrittura (POST/PATCH)p95 < 300 ms · p99 < 1000 msConfigurazione k6
Autenticazione (accesso/aggiornamento)p95 < 300 ms · p99 < 1000 msConfigurazione k6
Archiviazione (caricamento/download)p95 < 500 ms · p99 < 2000 msConfigurazione k6
Tasso di errore, tutti gli scenari< 1 %Configurazione k6
Un'incoerenza riscontrata durante la stesura di questo articolo

README.md nella cartella benchmarks/ documenta una soglia di lettura di p95 su < 200ms ("Supabase SLO"), mentre la soglia effettivamente applicata in benchmarks/k6/lib/config.js — quella in cui viene eseguito il test — è p(95)<500. I due file derivano l'uno dall'altro. Questo è un esempio concreto, trovato leggendo il codice sorgente di questo articolo, del perché un protocollo dovrebbe avere un'unica fonte di verità con versione anziché essere documentato in due posti: senza di essa, anche un team che cerca di essere rigoroso finisce per pubblicare soglie contrastanti.

Livello 3: confronto diretto tra PostgreSQL e API

Uno script Python (direct_vs_api.py) misura l'overhead effettivo del gateway + livello di servizio confrontando le richieste dirette psycopg2 con le chiamate HTTP sulla stessa operazione: elenco, lettura una tantum per ID, lettura filtrata e ordinata. Ogni misurazione segue un riscaldamento di 10 iterazioni prima del ciclo temporizzato, quindi calcola la media, p50, p95, p99 e un throughput in operazioni al secondo.

benchmarks/comparison/direct_vs_api.pypython
def percentile(data, p):
    k = (len(data) - 1) * (p / 100)
    f = int(k)
    c = f + 1
    if c >= len(data):
        return data[f]
    return data[f] + (k - f) * (data[c] - data[f])

Un secondo script (aurabase_vs_supabase.py) applica la stessa logica di riscaldamento e calcolo percentile a un confronto testa a testa con un'istanza locale di Supabase (CLI di Supabase, localhost:54321 per impostazione predefinita): stessa macchina, stessa rete locale per entrambi, esattamente la disciplina di parità dell'ambiente che PlanetScale documenta per i propri confronti.

Uno script di orchestrazione (collect_baseline.sh, target bench-baseline di Makefile) collega i tre livelli — Criterion sulle 3 casse, un sottoinsieme degli scenari k6 (health e crud-read oggi, non tutti e 8 ancora), quindi il confronto Python — e scrive log, JSON e report HTML Criterion in una cartella con timestamp univoco: benchmarks/results/AAAAMMJJ_HHMMSS/. Questo è esattamente il riflesso di una divulgazione datata, in un unico ciclo riproducibile, che la sezione seguente formalizza in un protocollo completo.

#
Metodologia

Il protocollo che applicheremo prima di pubblicare un dato

Otto impegni, ciascuno ancorato a una pratica già documentata da uno strumento o progetto riconosciuto di terze parti, non inventato per l’occasione.

  1. Preriscaldamento separato dalla misurazione. Criterion.rs riempie le cache della CPU/sistema operativo prima del cronometraggio; pgbench consiglia esplicitamente di non credere mai ad una corsa di pochi secondi.
  2. Durata fissa, non un numero fisso di iterazioni. Un carico ha bisogno di tempo per convergere: questo è il ruolo di stages k6 e il flag -T di pgbench.
  3. Percentili, mai solo la media — e vigilanza attiva sull'omissione coordinata se il generatore di carico opera in un circuito chiuso.
  4. Ambiente documentato in dettaglio: commit git del servizio testato, versione di PostgreSQL, specifiche hardware, versione dello strumento di caricamento. PlanetScale documenta i suoi esatti parametri TPCC (TABLES=20, SCALE=250, ~500 GB) proprio per questo motivo: senza questi dettagli nessuno può riprodurre una corsa.
  5. Risultati con timestamp e versione, mai un singolo numero inciso su una pagina di marketing senza una data. L'attrezzatura attuale è già scritta in un file datato; sarà necessario estendere questo riflesso a qualsiasi misurazione pubblicata pubblicamente, con la regione ospitante documentata come qualsiasi altra variabile ambientale (vedi la nostra guida sulla Sovranità ospitante dell'UE, rilevante non appena una cifra dipende da una determinata regione).
  6. Script e dati grezzi pubblicati insieme al risultato aggregato, non solo alla media finale. PlanetScale invita addirittura i lettori a segnalare un errore metodologico in un indirizzo dedicato – una postura che troviamo sana e che vogliamo riprendere.
  7. Throughput pubblicizzato insieme alla latenza, non solo l'uno o l'altro. Un sistema può avere un'eccellente latenza a basso carico e crollare nel throughput all'aumentare della concorrenza: questo è esattamente ciò che lo scenario breakpoint della nostra suite k6 (scale-to-crash) è progettato per rivelare e ciò che la misurazione del microbenchmark Throughput::Bytes di Criterion cattura a livello di funzione.
  8. Gap significativo prima di annunciare un miglioramento. Una variazione di qualche percentuale tra due esecuzioni potrebbe essere un rumore di misurazione piuttosto che un guadagno reale: Criterion.rs calcola la probabilità che la differenza osservata sia dovuta al caso prima di qualificarla come regressione o miglioramento. Un dato isolato, senza questa verifica, è solo un aneddoto statistico.
#
Impegno editoriale

Cosa non faremo

Questo elenco conta tanto quanto il protocollo positivo di cui sopra.

  • Confronto di diverse topologie (istanza self-hosted e gestita, fredda e preriscaldata) senza segnalarlo esplicitamente.
  • Conserva la migliore sequenza su dieci senza menzionare le altre nove.
  • Pubblica una figura senza data, senza versione di servizio, senza script di riproduzione.
  • Ripubblicare una figura di marketing esistente purché non sia riconducibile a questo protocollo.
  • Confrontarci con un concorrente su una cifra grezza della prestazione se quel concorrente non pubblica la propria metodologia in modo equivalente: una cifra contro il silenzio non è un confronto, è uno slogan.
Un esempio concreto, già corretto internamente

Una cifra come “avvio a freddo inferiore a 1 ms” è stata diffusa senza essere supportata da un benchmark riproducibile. Ora viene trattato internamente come non supportato e non deve essere letto come una caratteristica misurata del prodotto fino a quando qualsiasi misurazione datata, con metodologia pubblicata, non lo conferma. Questo è esattamente il tipo di affermazione che questo protocollo esiste per evitare che si ripeta.

#
Ripetibile

Il protocollo minimo per il benchmarking di qualsiasi backend

Questo protocollo non dipende da alcuno strumento Aurabase specifico: puoi applicarlo alla tua API oggi stesso.

  1. Imposta il caricamento prima di lo strumento: sola lettura, scrittura, mix realistico per la tua applicazione, non un rapporto generico copiato da un altro progetto.
  2. Separare esplicitamente la fase di preriscaldamento dalla fase di misurazione.
  3. Esegui il test per un tempo sufficiente: minuti, non secondi.
  4. Misura in percentili (p50/p95/p99), mai solo in media.
  5. Verificare che il generatore di carico non sia in circuito chiuso o correggere l'omissione di coordinamento nell'analisi.
  6. Isola l'ambiente sottoposto a test: nessun vicino rumoroso, nessuna attività in background concorrente.
  7. Pubblica la versione testata, la data, le specifiche hardware e lo script, non solo il risultato finale.

Su una semplice base Postgres, questo protocollo accetta un comando pgbench — 20 client simultanei distribuiti su 4 thread, per 5 minuti, con un rapporto sullo stato di avanzamento ogni 10 secondi:

terminalbash
# Inizializza il set di dati di test (fattore di scala >= numero di client)
pgbench -i -s 50 ma_base

# -c client simultanei, -j thread, -T durata in secondi, -P intervallo di reporting
pgbench -c 20 -j 4 -T 300 -P 10 ma_base
#
Strumenti

Strumenti di riferimento, per livello

Cinque strumenti, ciascuno adatto a un diverso livello dello stack: nessuno sostituisce gli altri.

Microfono (funzione)Criterio.rsCPU pura, statistiche di bootstrap
Interrogazione SQLpgbenchTransazione tipo TPC-B, tps e latenza
Carico HTTP/WSk6 (Grafana)Percentili, soglie di superamento/fallimento
OLTP su larga scalasysbench + TPCC (metodologia del telescopio)QPS, costo per prestazione
Correzione della misuraIstogramma HdrCompensa l'omissione coordinata
#
Domande frequenti

Domande frequenti

Perché Aurabase non pubblica ancora i numeri dei benchmark?+
Perché finora nessun dato relativo alle prestazioni è stato misurato secondo un protocollo pubblicato e riproducibile. Un dato come “avvio a freddo inferiore a 1 ms”, ad esempio, è stato diffuso senza essere supportato da un benchmark riproducibile: oggi è considerato infondato e non dovrebbe essere letto come una caratteristica misurata del prodotto. Questo articolo documenta il protocollo che seguiremo prima di pubblicare un risultato, proprio per evitare di ripetere questo tipo di affermazioni.
Cos'è il percentile p95 o p99 e perché non la media?+
Il p95 è il tempo di risposta al di sotto del quale si trova il 95% delle richieste: 1 richiesta su 20 è quindi più lenta. Il p99 spinge questa soglia a 1 richiesta su 100. La media nasconde queste richieste lente perché le diluisce nella massa delle richieste veloci; i percentili isolano la coda della distribuzione che gli utenti effettivamente notano.
Cos’è l’“omissione coordinata”?+
Si tratta di un bias di misurazione descritto dal progetto HdrHistogram: quando uno strumento di caricamento attende la risposta a una richiesta prima di inviare quella successiva (anello chiuso), una pausa del servizio riduce meccanicamente il numero di richieste lente registrate durante questa pausa. Il risultato finale può mostrare una latenza molto migliore di quella sperimentata da un utente reale.
Possiamo riprodurre noi stessi questi test?+
Il protocollo qui descritto (percentili, preriscaldamento separato, ambiente documentato, risultati datati) è applicabile a qualsiasi API, con strumenti pubblici (k6, pgbench, Criterion.rs, sysbench). Gli strumenti interni di Aurabase (la cartella benchmarks/repository) sono attualmente utilizzati per lo sviluppo e non sono ancora confezionati come suite pubblica con un clic. Crea un progetto per testare il tuo carico sull'API Aurabase con i tuoi script k6.
Qual è la differenza tra un percentile misurato e una soglia SLA?+
Un percentile (p95, p99) è una statistica calcolata a posteriori su misurazioni reali. Una soglia SLA (o una soglia k6 come p(95)<500) è un obiettivo fissato in anticipo, che il test verifica in modalità pass/fail. Confondere i due porta a presentare un obiettivo non raggiunto come un risultato ottenuto – è proprio questa la distinzione che questo protocollo richiede che sia mantenuta esplicita con ogni dato pubblicato.
Perché misurare il throughput oltre alla latenza?+
Un sistema può rispondere rapidamente a basso carico e vedere la sua latenza ridursi improvvisamente una volta superata una soglia di concorrenza: la latenza da sola non mostra dove si trova questa soglia. La misurazione del throughput (richieste o byte al secondo) insieme alla latenza rivela questo punto critico, che è qualcosa per cui lo scenario breakpoint della nostra suite k6 è specificamente progettato per trovare.

PRONTO PER L'IMPLEMENTAZIONE?

Il tuo backend in cinque minuti.

Nessuna carta di credito richiesta · 500 MB gratuiti · 50.000 MAU