10 nov 2025·8 min di lettura

gRPC streaming vs REST polling: quando conta davvero

Scopri quando scegliere gRPC streaming o REST polling, con esempi chiari per dashboard live e aggiornamenti di progresso, più appunti per mobile e firewall.

gRPC streaming vs REST polling: quando conta davvero

Il problema: chiedere aggiornamenti vs riceverli

Polling significa che il client interroga il server per aggiornamenti ancora e ancora, di solito con un timer (ogni 1 secondo, 5 secondi, 30 secondi).

Streaming significa che il client apre una sola connessione e il server continua a inviare aggiornamenti non appena accadono, senza aspettare la richiesta successiva.

Questa singola differenza è il motivo per cui streaming e polling possono sembrare simili in una demo piccola ma comportarsi in modo molto diverso in un prodotto reale. Con il polling scegli un compromesso a priori: aggiornamenti più veloci significano più richieste. Con lo streaming tieni aperta una linea e invii solo quando qualcosa cambia davvero.

In pratica, alcune cose tendono a spostarsi:

Polling è tanto aggiornato quanto l'intervallo scelto, mentre lo streaming può sembrare quasi istantaneo. Il polling genera anche molte risposte "niente è cambiato", che aumentano i costi da entrambe le parti (richieste, header, controlli auth, parsing). Su mobile, il polling frequente mantiene la radio attiva più spesso, il che può consumare batteria e dati. E poiché il polling campiona lo stato, può perdere cambiamenti rapidi tra gli intervalli, mentre uno stream ben progettato può consegnare eventi in ordine.

Un esempio semplice è una dashboard operativa live che mostra nuovi ordini e il loro stato. Polling ogni 10 secondi può andare bene in una giornata lenta. Ma quando il team si aspetta aggiornamenti entro 1 secondo, il polling o sembra lento o comincia a sovraccaricare il server.

Non tutte le app hanno bisogno del real-time. Se gli utenti controllano una pagina di tanto in tanto (come report mensili), il polling ogni minuto, o semplicemente l'aggiornamento su richiesta, è spesso la scelta più semplice e migliore.

Situazioni in cui il polling comincia a far male

Il polling sembra semplice: il client chiede "c'è qualcosa di nuovo?" ogni N secondi. Funziona quando gli aggiornamenti sono rari, il numero di utenti è piccolo o ritardare di qualche secondo non è un problema.

Il dolore inizia quando hai bisogno di freschezza frequente, molti utenti o entrambi.

Le dashboard live sono il caso classico. Pensate a uno schermo ops che mostra ticket aperti, errori di pagamento e allarmi rossi. Se i numeri cambiano ogni pochi secondi, il polling o resta indietro (gli utenti perdono i picchi) oppure bombarda la tua API (i server spendono tempo a rispondere "nessun cambiamento" di continuo).

Gli aggiornamenti di progresso sono un'altra trappola comune. Upload di file, generazione di report e elaborazione video spesso durano minuti. Polling ogni secondo fa sembrare l'interfaccia "live", ma crea molte richieste extra e resta comunque scattoso perché il client vede solo snapshot.

Arrivi imprevedibili peggiorano la situazione. Chat, code di supporto e nuovi ordini possono essere silenziosi per 10 minuti e poi esplodere per 30 secondi. Con il polling paghi il costo durante i periodi quieti e rischi comunque ritardi durante il burst.

Segnali in stile IoT lo accentuano ancora. Quando tracci lo stato online/offline di dispositivi, last seen e metriche piccole, puoi avere migliaia di piccoli cambiamenti che si sommano. Il polling moltiplica questo in un flusso costante di richieste.

Di solito il polling comincia a far male quando vedi pattern come: team che abbassano l'intervallo a 1–2 secondi solo per apparire reattivi; la maggior parte delle risposte non contiene aggiornamenti ma brucia comunque header e auth; il carico server cresce con le tab aperte invece che con cambi reali; utenti mobile si lamentano di batteria e dati; i picchi di traffico avvengono quando le persone aprono le dashboard, non quando avvengono gli eventi di business.

Perché lo streaming può battere il polling nella pratica

Il vantaggio principale dello streaming è semplice: smetti di chiedere al server la stessa cosa più e più volte quando la risposta è di solito "nessun cambiamento". Con il polling, l'app continua a inviare richieste su un timer solo per scoprire che non è successo nulla. Questo crea traffico sprecato, parsing extra e più probabilità di timeout.

Con lo streaming, il server mantiene una connessione aperta e spinge nuovi dati solo quando qualcosa cambia. Se lo stato di un ordine cambia, una metrica supera una soglia o un job di background passa dal 40% al 41%, l'aggiornamento può arrivare subito invece di aspettare la finestra di polling successiva.

Questa latenza inferiore non riguarda solo la velocità. Cambia la percezione dell'interfaccia. Il polling spesso produce "scatti": appare uno spinner, i dati si aggiornano a ondate e i numeri saltano in avanti. Lo streaming tende a produrre aggiornamenti più piccoli e frequenti, che risultano più fluidi e affidabili.

Lo streaming può anche semplificare il lavoro lato server. Il polling spesso restituisce una risposta completa ogni volta, anche se il 99% è identico alla precedente. Con uno stream puoi inviare solo i cambiamenti, riducendo byte, letture ripetute dal database e serializzazione inutile.

In pratica il contrasto è questo: il polling crea molte richieste brevi che spesso rispondono "niente di nuovo"; lo streaming usa una connessione a vita più lunga e invia messaggi solo quando necessario. La latenza del polling è legata all'intervallo scelto (2 s, 10 s, ecc.). La latenza dello streaming è legata all'evento stesso (l'aggiornamento avviene, l'utente lo vede). Le risposte di polling sono spesso snapshot completi, mentre gli stream possono inviare piccoli delta.

Tornando all'esempio della dashboard ticket: con polling ogni 5 secondi sprechi chiamate nei periodi silenziosi o accetti che la dashboard sia sempre qualche secondo indietro. Con lo streaming i periodi silenziosi restano tali, e quando arriva un ticket l'interfaccia si aggiorna immediatamente.

I pattern di streaming che le persone usano davvero

Quando la gente immagina lo streaming spesso pensa a una grande "connessione live" che risolve tutto. In pratica i team usano pochi pattern semplici, ognuno adatto a un tipo diverso di aggiornamento.

Questo è il pattern più comune: il client apre una chiamata e il server continua a inviare nuovi messaggi man mano che si verificano. Si adatta a qualsiasi schermo dove gli utenti guardano cambiamenti.

Una dashboard ops live è un esempio chiaro. Invece che il browser chieda "nuovi ordini?" ogni 2 secondi, il server invia un aggiornamento non appena arriva un nuovo ordine. Molti team mandano anche heartbeat occasionali così l'interfaccia può mostrare "connesso" e rilevare connessioni rotte più velocemente.

La stessa idea si applica agli aggiornamenti di progresso. Se un report impiega 3 minuti, il server può streammare milestone (queued, 10%, 40%, generating PDF, done) così l'utente vede movimento senza spammare il server.

Qui il client invia molti piccoli eventi in modo efficiente su una sola chiamata, e il server risponde una volta alla fine (o solo con un sommario finale). È utile quando hai burst di dati.

Pensate a un'app mobile che cattura letture sensoriali o a un'app POS che bufferizza azioni offline. Quando la rete è disponibile può streammare un batch di eventi con meno overhead rispetto a centinaia di richieste REST separate.

3) Bidirectional streaming (due vie)

Serve per conversazioni continue dove entrambe le parti possono parlare in qualsiasi momento. Uno strumento di dispatch può inviare comandi a un'app sul campo mentre l'app streamma lo stato indietro. Anche la collaborazione live (più utenti che modificano lo stesso record) può rientrare.

La request-response rimane la scelta migliore quando il risultato è una singola risposta, gli aggiornamenti sono rari o hai bisogno del percorso più semplice attraverso cache, gateway e monitoraggio.

Come decidere e progettarlo passo dopo passo

Pilota un solo stream hot
Spedisci prima uno schermo pilota, misura lag e disconnessioni, poi espandi con fiducia.
Inizia ora

Inizia scrivendo cosa deve veramente cambiare sullo schermo immediatamente e cosa può aspettare qualche secondo. La maggior parte dei prodotti ha solo una piccola fetta "calda": un contatore live, una barra di progresso, un badge di stato.

Dividi gli aggiornamenti in due categorie: real-time e "va bene dopo". Per esempio, una dashboard di supporto potrebbe aver bisogno che i nuovi ticket compaiano immediatamente, mentre i totali settimanali possono aggiornarsi ogni minuto senza che nessuno se ne accorga.

Poi nomina i tipi di eventi e mantieni ogni aggiornamento piccolo. Non inviare tutto l'oggetto ogni volta se cambia solo un campo. Un approccio pratico è definire eventi come TicketCreated, TicketStatusChanged e JobProgressUpdated, ognuno con solo i campi necessari all'interfaccia.

Un flusso di progettazione utile:

  • Marca ogni elemento UI con il suo ritardo massimo (100 ms, 1 s, 10 s).
  • Definisci i tipi di evento e il payload minimo per ciascuno.
  • Decidi come i client si riprendono dopo una disconnessione (snapshot completo o resume da un cursore).
  • Imposta regole per client lenti (batch, collassa, scarta aggiornamenti vecchi o invia meno frequentemente).
  • Scegli un piano di fallback quando lo streaming non è disponibile.

Il comportamento di reconnessione è dove molti team si bloccano. Un default solido è: alla connessione invia uno snapshot (stato corrente), poi invia eventi incrementali. Se supporti il resume, includi un cursore come "last event id" così il client può chiedere "mandami tutto dopo 18452." Questo rende le riconnessioni prevedibili.

Il backpressure è semplicemente il problema "e se il client non riesce a stare al passo?". Per una dashboard live spesso va bene collassare aggiornamenti. Se il progresso va 41%, 42%, 43% mentre il telefono è occupato, puoi inviare solo 43%.

Pianifica anche un fallback che mantenga il prodotto utilizzabile. Scelte comuni sono uno switch temporaneo al polling ogni 5–15 secondi, o un pulsante di refresh manuale per schermate meno critiche.

Se stai costruendo in AppMaster, questo spesso si mappa bene a due percorsi: un flow event-driven per gli aggiornamenti "caldi" e una normale API read per lo snapshot di fallback.

Esempio reale: dashboard live e aggiornamenti di progresso

Immagina una dashboard di magazzino che mostra livelli di inventario per 200 SKU. Con polling REST, il browser potrebbe chiamare /inventory ogni 5 secondi, ricevere una lista JSON completa e ridipingere la tabella. La maggior parte del tempo nulla cambia, ma paghi comunque il costo: richieste ripetute, risposte complete ripetute e parsing ripetuto.

Con lo streaming il flusso si inverte. Il client apre uno stream long-lived. Riceve prima uno snapshot iniziale (così l'interfaccia può renderizzare subito), poi solo piccole modifiche quando qualcosa cambia.

Una vista tipica di dashboard diventa:

  • Stato iniziale: lista completa di SKU, quantità e un timestamp "ultimo aggiornamento" per riga.
  • Aggiornamenti incrementali: solo le righe che sono cambiate (per esempio, SKU-184 è passato da 12 a 11).
  • Segnale di freschezza: un "dati aggiornati al" globale, così gli utenti si fidano di quello che vedono.

Aggiungi una seconda schermata: un job long-running, come importare un CSV o generare fatture mensili. Il polling spesso produce salti goffi: 0%, 0%, 0%, 80%, done. Lo streaming lo rende onesto e calmo.

Un stream di progresso tipico invia piccoli snapshot frequenti:

  • Percentuale completata (0–100)
  • Step corrente ("Validating", "Matching", "Writing")
  • ETA (best-effort e modificabile)
  • Risultato finale (success, warnings, o un messaggio di errore)

Una scelta di progettazione chiave è delta vs snapshot. Per l'inventario i delta sono ottimi perché sono minuscoli. Per il progresso dei job gli snapshot sono spesso più sicuri perché ogni messaggio è già piccolo e riducono la confusione se un client si riconnette e perde un messaggio.

Se costruisci app su una piattaforma come AppMaster, questo tipicamente si mappa a un read model (stato iniziale) più aggiornamenti in stile evento (delta), così la UI resta reattiva senza martellare la tua API.

Cosa cambia per i client mobile

Rendi gli aggiornamenti di progresso fluidi
Prototipa aggiornamenti di progresso con uno snapshot netto e piccoli cambi incrementali.
Prova AppMaster

Su un telefono una "connessione continua" si comporta diversamente che su desktop. Le reti cambiano tra Wi-Fi e cellulare, i tunnel si resettano e gli utenti entrano in ascensore. Il grande cambiamento è che smetti di pensare a singole richieste e inizi a pensare a sessioni che possono scomparire in qualsiasi momento.

Aspettati disconnessioni e progetta per replay sicuri. Un buon stream include un cursore come "last event id" così l'app può riconnettersi e dire "riprendi da qui." Senza questo, gli utenti vedono aggiornamenti duplicati (lo stesso step di progresso due volte) o mancano aggiornamenti (salto da 40% a 90%).

La batteria spesso migliora con lo streaming perché l'app evita continui wakeup per il polling. Ma questo vale solo se i messaggi sono piccoli e significativi. Inviare oggetti interi ogni secondo è un modo rapido per consumare dati e batteria. Preferisci eventi compatti come "order 183 status changed to Shipped" invece di rimandare l'intero ordine.

Quando l'app è in background lo streaming viene spesso messo in pausa o terminato dall'OS. Pianifica un fallback chiaro: mostra l'ultimo stato noto, poi sincronizza al foreground. Per eventi urgenti usa le push notification della piattaforma e lascia che l'app apra e si risincronizzi quando l'utente tocca.

Un approccio pratico per dashboard mobile e aggiornamenti di progresso:

  • Riconnetti con backoff (aspetta un po' più a lungo dopo ogni fallimento) per evitare di drenare la batteria in copertura scarsa.
  • Includi un id evento o un timestamp e rendi gli aggiornamenti idempotenti così i duplicati non rompono l'interfaccia.
  • Invia delta quando ha senso e batcha aggiornamenti a bassa priorità.
  • Invia uno snapshot alla connessione così l'interfaccia parte corretta, poi applica eventi live.
  • Aggiungi una versione semplice (tipo di messaggio più campi opzionali) così le versioni vecchie dell'app continuano a funzionare.

Se costruisci app mobile con AppMaster, tratta lo stream come "gradito quando disponibile", non come "l'unica fonte di verità". L'interfaccia dovrebbe restare utilizzabile durante brevi disconnessioni.

Firewall, proxy e i trabocchetti di HTTP/2

Testa il comportamento mobile presto
Crea app native iOS e Android che restano usabili durante disconnessioni e backgrounding.
Costruisci mobile

Lo streaming può sembrare una vittoria teorica finché non entrano in gioco le reti reali. La grande differenza è la connessione: lo streaming spesso significa una singola connessione HTTP/2 long-lived, e questo può infastidire proxy aziendali, middlebox e settaggi di sicurezza rigidi.

Le reti aziendali talvolta usano TLS inspection (un proxy che decripta e ricripta il traffico). Questo può rompere la negoziazione HTTP/2, bloccare stream long-lived o degradare il comportamento in modi difficili da individuare. I sintomi sono disconnessioni casuali, stream che non partono mai o aggiornamenti che arrivano a ondate invece che fluidi.

Il supporto HTTP/2 è obbligatorio per il gRPC classico. Se un proxy parla solo HTTP/1.1 le chiamate possono fallire anche se il REST normale funziona. Per questo gli ambienti browser spesso usano gRPC-Web, che è progettato per passare più facilmente attraverso l'infrastruttura HTTP comune.

Load balancer, idle timeout e keepalive

Anche quando la rete permette HTTP/2, l'infrastruttura spesso ha idle timeout. Uno stream che resta silenzioso per un po' può essere chiuso da un load balancer o proxy.

Rimedi comuni:

  • Imposta keepalive sensati su server e client (non troppo frequenti).
  • Aumenta gli idle timeout su load balancer e reverse proxy.
  • Invia piccoli heartbeat quando sono normali lunghi periodi di silenzio.
  • Gestisci le riconnessioni in modo pulito (resume di stato, evitare eventi duplicati).
  • Logga i motivi di disconnessione sia client che server.

Quando preferire gRPC-Web o un fallback

Se gli utenti stanno dietro reti aziendali molto chiuse, tratta lo streaming come best-effort e fornisci un canale di fallback. Una divisione comune è mantenere lo streaming gRPC per le app native, ma permettere gRPC-Web (o brevi poll REST) quando la rete si comporta come un proxy browser.

Testa dagli stessi posti dove lavorano i tuoi utenti:

  • Una rete aziendale con policy proxy
  • Wi‑Fi pubblico
  • Una connessione VPN
  • Rete di un operatore mobile

Se distribuisci con AppMaster su AppMaster Cloud o un cloud principale, convalida questi comportamenti end-to-end, non solo in sviluppo locale.

Errori comuni e trappole

La trappola più grande è trattare lo streaming come default. Il real-time fa piacere, ma può aumentare silenziosamente carico server, uso batteria mobile e ticket di supporto. Parti essendo rigoroso su quali schermate richiedono veramente aggiornamenti entro secondi e quali possono aggiornarsi ogni 30–60 secondi.

Un altro errore comune è inviare l'oggetto completo a ogni evento. Una dashboard live che spinge un blob JSON da 200 KB ogni secondo sarà real-time fino al primo ora di punta. Preferisci piccoli delta: "order 4832 status changed to shipped" invece di "ecco di nuovo tutti gli ordini".

La sicurezza viene trascurata più spesso di quanto si ammetta. Con stream long-lived serve comunque auth e autorizzazioni solide, e bisogna pianificare l'expiry del token a metà stream. Se un utente perde accesso a un progetto, il server dovrebbe smettere immediatamente di inviare aggiornamenti.

Il comportamento di reconnessione è dove molte app si rompono nel mondo reale, specialmente su mobile. I telefoni cambiano rete, vanno in sleep e vengono mandati in background. Alcune buone pratiche prevengono i peggiori guai: assumere disconnessioni; riprendere da last-seen event id (o timestamp); rendere gli aggiornamenti idempotenti così i retry non duplicano azioni; impostare timeout e keepalive chiari per reti lente; offrire una modalità degradata (refresh meno frequente) quando lo streaming fallisce.

Infine, i team lanciano lo streaming senza visibilità. Monitora rate di disconnessione, loop di reconnessione, lag dei messaggi e aggiornamenti persi. Se lo stream di progresso mostra 100% sul server ma i client restano al 70% per 20 secondi, ti servono metriche che mostrino dove è il ritardo (server, rete o client).

Checklist rapida prima di scegliere lo streaming

Progetta i dati una volta sola
Modella i tuoi dati in tabelle PostgreSQL-first, poi rilascia UI che restano accurate sotto carico.
Crea app

Decidi cosa "real-time" significa davvero per i tuoi utenti.

Inizia dalla latenza. Se una dashboard deve sentirsi live, aggiornamenti sotto 1 secondo possono giustificare uno stream. Se gli utenti hanno bisogno solo di un refresh ogni 10–60 secondi, il polling semplice spesso vince per costo e semplicità.

Poi guarda il fan-out. Un singolo feed di dati visto da molte persone contemporaneamente (una dashboard ops su uno schermo a muro più 50 browser) può trasformare il polling in carico di background costante. Lo streaming può tagliare le richieste ripetute, ma devi comunque gestire molte connessioni aperte.

Una checklist rapida di decisione:

  • Quanto velocemente devono apparire i cambiamenti: sotto 1 secondo, intorno a 10 secondi, o circa un minuto?
  • Quanti client guarderanno gli stessi dati contemporaneamente e per quanto tempo?
  • Cosa deve succedere se il client è offline per 30 secondi: mostrare dati obsoleti, bufferizzare aggiornamenti o ricaricare lo stato?
  • Il percorso di rete può supportare HTTP/2 end-to-end, inclusi proxy e load balancer?
  • Hai un fallback sicuro (tipo polling temporaneo) se lo streaming si rompe in produzione?

Pensa anche a fallimento e recupero. Lo streaming è ottimo quando funziona, ma la parte difficile sono reconnessioni, eventi mancanti e mantenere UI consistente. Un design pratico è usare lo streaming per il percorso veloce, ma definire un'azione di resync (una chiamata REST) che ricostruisca lo stato corrente dopo la reconnessione.

Se prototipi rapidamente una dashboard (per esempio con una UI no-code in AppMaster), applica questa checklist presto così non sovrasviluppi il backend prima di capire i reali bisogni di aggiornamento.

Prossimi passi: pilota uno stream piccolo ed espandi in sicurezza

Tratta lo streaming come qualcosa da guadagnare, non come un interruttore da accendere. Scegli un punto dove la freschezza vale chiaramente lo sforzo e lascia tutto il resto com'è finché non hai dati.

Inizia con un singolo stream ad alto valore, come aggiornamenti di progresso per un task lungo (import file, generazione report) o una card su una dashboard live (ordini di oggi, ticket attivi, lunghezza coda corrente). Mantenere lo scope piccolo rende anche più facile confrontare con il polling con numeri reali.

Un piano pilota semplice:

  • Definisci il successo: latenza target, tasso di disconnessione accettabile e cosa significa "sufficientemente buono" su mobile.
  • Rilascia uno stream minimale: un tipo di messaggio, una schermata, un endpoint backend.
  • Misura le basi: CPU e memoria server, connessioni aperte, lag dei messaggi, frequenza di reconnessione e impatto sulla batteria client.
  • Aggiungi un fallback: se lo stream fallisce o la rete lo blocca, passa automaticamente a una modalità di polling più lenta.
  • Espandi con cautela: aggiungi campi o schermate solo dopo poter spiegare le metriche.

Tieni il fallback intenzionale. Alcune reti aziendali, proxy più vecchi o firewall rigidi interferiscono con HTTP/2, e le reti mobili diventano instabili quando l'app va in background. Un downgrade elegante evita schermi vuoti e ticket di supporto.

Se vuoi rilasciare questo senza troppo codice custom, AppMaster (appmaster.io) può aiutarti a costruire logica backend, API e UI rapidamente, poi iterare quando i requisiti cambiano. Parti piccolo, dimostra il valore e aggiungi stream solo dove battano chiaramente il polling.

Facile da avviare
Creare qualcosa di straordinario

Sperimenta con AppMaster con un piano gratuito.
Quando sarai pronto potrai scegliere l'abbonamento appropriato.

Iniziare