Che cos'è il connection pooling serverless?

Aggiornato: ottobre 2026

Il connection pooling serverless è una tecnica che condivide poche connessioni reali al database tra molte istanze di funzioni di breve durata. Esiste perché due modelli di scalabilità non vanno d’accordo: il calcolo serverless risponde al carico moltiplicando le istanze, mentre un database tratta ogni connessione come una risorsa costosa, sostenuta da memoria e con un tetto rigido. Messi insieme in modo ingenuo, un picco di traffico modesto diventa un’interruzione too many connections.

Punti chiave

DomandaRisposta
La collisioneLe funzioni scalano per clonazione; le connessioni sono limitate e costose
Il sintomoFATAL: sorry, too many clients already durante i picchi
La soluzioneUn pooler multiplexa molti client su poche connessioni reali
La manopolaPooling per transazione vs. per sessione – condivisione vs. compatibilità
La risposta BaaSI client parlano HTTPS stateless; la piattaforma possiede il pool

Il guasto, osservato dal database

-- Che cosa vede il database durante un picco di traffico serverless:
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state;
--  active               |   14
--  idle                 |  483     ← parcheggiate dalle istanze di funzione calde
SHOW max_connections;    --  100    ← il tetto che hanno già sfondato

-- Ogni connessione è un processo reale che occupa memoria reale –
-- ecco perché il tetto esiste e perché alzarlo non è la soluzione.

La forma del problema: ogni istanza di funzione apre la propria connessione, la tiene durante i tempi morti tra un’invocazione e l’altra, e il numero di istanze lo decide il traffico, non chi sviluppa. Il riuso avviene solo dentro un’istanza calda – mai tra istanze diverse – quindi una concorrenza di 300 significa 300 pool a connessione singola. Alzare max_connections compra margine al prezzo di memoria reale e perde contro il picco successivo, più grande.

Su un backend gestito, il codice applicativo esce del tutto da questa lotta – le chiamate SDK sono richieste HTTPS stateless, e nessun client detiene mai una connessione al database:

// JavaScript / Node.js — Back4app JS SDK
// Inside a serverless function: no driver, no pool, no connection to leak.
// Each SDK call is a stateless HTTPS request; pooling happens platform-side.
Parse.initialize('APP_ID', 'JS_KEY');
Parse.serverURL = 'https://parseapi.back4app.com';

export async function handler(event) {
  const query = new Parse.Query('Order');
  query.equalTo('status', 'pending');
  query.limit(20);
  const orders = await query.find();  // request returns; nothing stays open
  return orders.map((o) => o.id);
}
// 1,000 concurrent invocations = 1,000 HTTP requests,
// not 1,000 database connections.

Come un pooler assorbe il fan-out

Pooler di connessioni tra le funzioni serverless e il databaseCentinaia di istanze di funzioni di breve durata aprono connessioni client economiche verso un pooler, che le multiplexa su un piccolo insieme fisso di connessioni reali al database, mantenendo il database sotto il suo limite di connessioni.

20 connessioni reali

i client attendono un istante in coda
invece di fallire

Funzione ×500
(picco)

Pooler
(es. PgBouncer)

Funzione ×500
(picco successivo)

Database
max_connections: 100

Centinaia di istanze di funzioni di breve durata aprono connessioni client economiche verso un pooler, che le multiplexa su un piccolo insieme fisso di connessioni reali al database, mantenendo il database sotto il suo limite di connessioni.

Un pooler come PgBouncer accetta connessioni client a migliaia – ciascuna economica dal suo lato – e presta connessioni server reali da un piccolo pool solo quando arriva del lavoro. Il database vede venti connessioni tranquille; cinquecento funzioni credono di averne una ciascuna. Quando la domanda supera il pool, i client attendono millisecondi in coda invece di ricevere errori – un fallimento secco si converte in una latenza modesta.

Il dimensionamento del pool è il punto in cui l’intuizione fallisce di più. Il parallelismo utile di un database è limitato da core e disco – il throughput di solito raggiunge il picco con un pool di poche decine di connessioni, intorno al numero di core per due, e poi cala man mano che altre connessioni aggiungono contesa. L’aritmetica del pooler funziona perché le richieste serverless sono brevi: una connessione che serve una transazione da 8 ms può servirne ben più di cento al secondo, quindi venti connessioni reali assorbono comodamente migliaia di invocazioni di funzioni. Il pool non è una cache di comodo; è un collo di bottiglia deliberato, piazzato dove mettersi in coda costa poco.

La manopola cruciale è quanto dura il prestito.

Pooling per transazione vs. pooling per sessione

DimensionePooling per sessionePooling per transazione
Durata del prestitoL’intera sessione del clientUna transazione, poi la connessione viene recuperata
Moltiplicatore di condivisioneBasso – i client inattivi parcheggiano connessioniAlto – ideale per il lavoro serverless breve
Prepared statementPienamente supportatiSolo tramite supporto a livello di protocollo, configurato esplicitamente
Stato di sessione (SET, tabelle temporanee, LISTEN/NOTIFY)FunzionaSi rompe – transazioni diverse possono finire su connessioni diverse
Ideale perApp di lunga durata, strumenti di amministrazione, migrazioniTraffico richiesta/risposta web e serverless

La modalità transazione è ciò che rende praticabili i carichi serverless – una funzione che esegue una transazione da 8 ms non dovrebbe possedere una connessione per i minuti della sua vita a caldo – ma non è gratis: tutto ciò che presume che “la propria connessione” persista tra un’istruzione e l’altra diventa un bug subdolo. Il consiglio consolidato: pooling per transazione per il traffico di richieste, connessione diretta o con pool di sessione per le migrazioni e per tutto ciò che ha stato.

Casi d’uso tipici

  • Funzioni serverless ed edge che interrogano SQL. Il caso canonico – numeri di istanze a picchi contro un budget di connessioni fisso.
  • Molti piccoli servizi, un solo database. Venti servizi × pool predefiniti da dieci connessioni = 200 connessioni che nessuno aveva pianificato; un pooler condiviso ristabilisce un’aritmetica sana.
  • Piattaforme multi-tenant. I carichi per tenant moltiplicano la domanda di connessioni; il pooling permette di far rispettare il budget del database condiviso.
  • Raffiche di traffico su database modesti. I picchi del giorno del lancio si mettono in coda al pooler per millisecondi invece di generare errori nel database.
  • Proteggere il primario durante gli incidenti. Un pool di dimensione fissa è una paratia: i client fuori controllo esauriscono la coda del pooler, non la memoria del database.

Conviene gestire un pooler in proprio? Matrice decisionale

Gestire un pooler quando…Lasciar perdere quando…
Funzioni o molti servizi si collegano direttamente a SQLUn BaaS gestito termina il traffico dei client nel proprio livello API
Compaiono errori di connessione sotto i picchi di caricoIl traffico è costante e arriva da pochi server di lunga durata con pool lato client
Il database e il suo budget sono gestiti in proprioLa piattaforma fa già pooling tra il livello API e il database
Tenant o team condividono un unico databaseIl carico è una sola app, un solo pool, ben dentro i limiti
C’è capacità operativa per un componente critico in piùNessuno è in reperibilità per il pooler

L’asimmetria, detta onestamente: un pooler risolve l’esaurimento delle connessioni; un backend gestito lo dissolve. Quando i client parlano HTTPS con API generate automaticamente, il fan-out non raggiunge mai il livello database – il pooling avviene comunque, ma come infrastruttura collaudata di qualcun altro anziché come componente da gestire in proprio.

Limiti e trade-off

  • Un pooler è un componente. Richiede deployment, monitoring, failover e aggiornamenti – si è scambiato un problema di risorse con un problema operativo, a un cambio favorevole ma non nullo.
  • La modalità transazione cambia la semantica. Prepared statement, variabili di sessione e advisory lock smettono di comportarsi come documentato; i fallimenti sono intermittenti e dipendono dal carico – il tipo peggiore.
  • Un salto in più costa latenza. Di norma sotto il millisecondo dentro la rete, ma sta sul percorso di ogni query.
  • Il pooler può essere il collo di bottiglia. Un pooler a thread singolo sotto un picco violento accumula una coda profonda; il tetto si è spostato, non è sparito.
  • Il pooling non corregge le query lente. Raziona le connessioni; una query che tiene il prestito per secondi lascia il pool a secco. Query veloci – e gli indici dietro di esse – restano la vera leva di capacità.

Il connection pooling su Back4app

Back4app è una piattaforma open-source di Backend as a Service (BaaS) che combina database gestito, API REST e GraphQL generate automaticamente, autenticazione, archiviazione di file e funzioni serverless con Cloud Code. La sua architettura risponde alla domanda sul pooling in modo strutturale: le app client e le funzioni Cloud Code emettono richieste HTTPS stateless, ed è il livello server della piattaforma – non il codice applicativo – a mantenere pool di connessioni di lunga durata e dimensionati correttamente verso il database gestito. Il fan-out delle istanze sul lato di calcolo non si traduce mai in fan-out di connessioni sul lato database, che è esattamente la proprietà che tutto questo articolo esiste per costruire.

Domande frequenti

Perché il serverless esaurisce le connessioni al database?

Perché due modelli di scalabilità entrano in collisione: il calcolo serverless moltiplica le istanze a ogni richiesta, mentre un database dispone di un budget di connessioni fisso – spesso intorno a 100 per impostazione predefinita. Ogni istanza di funzione apre la propria connessione, la tiene durante i tempi morti, e un picco di traffico che genera 500 istanze chiede 500 connessioni in una volta sola. Il database rifiuta l'eccedenza, e query che non c'entrano nulla iniziano a fallire.

Che cosa fa davvero un pooler di connessioni come PgBouncer?

Si colloca tra il codice e il database, accetta migliaia di connessioni client economiche e le multiplexa su un piccolo pool di connessioni server reali. I client credono di detenere una connessione; in realtà ne prendono una in prestito per una transazione o una sessione e poi la restituiscono. Il database vede un insieme di connessioni calmo e fisso, a prescindere da quante funzioni si avviano.

Qual è la differenza tra pooling per transazione e pooling per sessione?

La durata del prestito. Il pooling per sessione assegna una connessione reale per l'intera sessione del client – sicuro per ogni funzionalità, ma un client inattivo parcheggia comunque una connessione. Il pooling per transazione presta la connessione solo mentre una transazione è in corso, poi la recupera: la condivisione si moltiplica enormemente, ma lo stato di sessione si rompe – prepared statement, variabili di sessione e LISTEN/NOTIFY richiedono attenzione, altrimenti falliscono.

Perché le connessioni schizzano quando le funzioni scalano?

Una piattaforma serverless gestisce la concorrenza clonando le istanze, e ogni clone inizializza il proprio client del database. Il riuso delle connessioni avviene solo dentro una singola istanza calda, mai tra istanze diverse. Una concorrenza di 300 significa quindi 300 pool di dimensione uno – la forma peggiore possibile: tutto il sovraccarico del pooling senza alcuna condivisione. Il fan-out è strutturale, non un bug nel codice.

Quanto dovrebbe essere grande un pool di connessioni al database?

Molto più piccolo di quanto suggerisca l'intuizione. Il throughput di solito raggiunge il massimo con un pool vicino al parallelismo reale del database – una regola empirica comune è il numero di core per due, corretto per le attese su disco – non nelle centinaia. Oltre quel punto, le connessioni in più aggiungono contesa e costo in memoria senza aggiungere throughput. Il mestiere del pooler è proprio far sembrare infinito un pool piccolo a chi lo chiama.

Serve ancora un pooler usando un BaaS?

Non per il proprio traffico – è proprio questo il punto. Un backend gestito termina le richieste dei client come chiamate HTTPS stateless nel livello API; il suo livello server mantiene verso il database pool di lunga durata e dimensionati correttamente. Funzioni e app non detengono mai connessioni al database, quindi lo scenario di esaurimento sparisce invece di essere mitigato. I pooler tornano in gioco solo collegando direttamente strumenti esterni.

Quali sono gli svantaggi dei pooler di connessioni?

Aggiungono un salto di rete e quindi latenza, diventano un componente da far girare e monitorare, e la modalità transazione cambia la semantica in silenzio – le funzionalità legate alla sessione smettono di comportarsi come documentato. Un singolo processo pooler può diventare a sua volta il collo di bottiglia sotto un carico a picchi, e dimensionarlo male sposta soltanto la coda. È infrastruttura essenziale, ma è infrastruttura.

Termini correlati

Confronta con

Fonti di approfondimento

Pronto a costruire il tuo backend?

Avvia il tuo progetto su Back4app in pochi minuti: database, autenticazione, API e Cloud Code inclusi. Nessuna carta di credito richiesta.

Scritto e revisionato da Back4app Engineering, Back4app Engineering · Pubblicato il 2026-10-23