---
term: 'Server-Sent Events vs. WebSocket vs. polling'
seoTitle: 'SSE vs. WebSocket vs. polling: scegliere il trasporto'
headline: 'Server-Sent Events vs. WebSocket vs. polling: quale scegliere?'
slug: sse-vs-websockets-vs-polling
category: api-realtime
shortDefinition: 'Il polling è un modello pull in cui il client chiede in continuazione; SSE e WebSocket tengono aperta una connessione perché il server spinga in tempo reale.'
relatedTerms:
  - websockets-real-time-sync
  - real-time-live-queries
  - pub-sub-pattern
  - api-payload-optimization
contrastsWith:
  - websockets-real-time-sync
aboutTerms:
  - 'Server-Sent Events (SSE)'
  - 'WebSockets'
  - 'Long Polling'
  - 'Short Polling'
faq:
  - question: 'Che cosa conviene, SSE o WebSocket?'
    answer: 'Nessuno dei due in assoluto – la vera domanda è la direzione. SSE è lo strumento più semplice quando i dati scorrono in un solo senso, dal server al client: HTTP ordinario, riconnessione automatica, passaggio senza attriti dai proxy comuni. I WebSocket si guadagnano la complessità in più quando anche il client deve inviare in tempo reale: chat, giochi, editing collaborativo.'
  - question: 'SSE è più veloce del polling?'
    answer: 'Sulla latenza di consegna, in modo netto: gli eventi arrivano nel momento in cui si verificano, mentre il polling costa in media metà dell''intervallo più un andata e ritorno. È anche più economico – una sola connessione trattenuta invece di una serie di cicli richiesta/risposta quasi sempre vuoti, ognuno dei quali paga per intero l''overhead degli header HTTP.'
  - question: 'Quando conviene usare il long polling?'
    answer: 'Come ripiego, non come prima scelta: esiste per gli ambienti in cui le connessioni persistenti non funzionano – intermediari legacy, proxy che rimuovono gli upgrade WebSocket o che mettono gli stream in buffer. Il server tiene aperta ogni richiesta fino all''arrivo dei dati, il che approssima il push al prezzo di un andirivieni di riconnessioni e di header pagati a ogni richiesta.'
  - question: 'Quante connessioni SSE può aprire un browser?'
    answer: 'Su HTTP/1.1, sei per origine – e il limite è condiviso fra le schede, un''insidia ben documentata in cui una dashboard aperta in sette schede resta a digiuno in silenzio. Su HTTP/2 il vincolo si sposta sugli stream concorrenti multiplexati su una sola connessione (circa cento per impostazione predefinita), il che manda il problema in pensione.'
  - question: 'SSE si riconnette automaticamente?'
    answer: 'Sì – è la caratteristica che più lo distingue dai WebSocket grezzi. EventSource ritenta da solo le connessioni cadute, rispetta l''intervallo di retry fissato dal server e rimanda l''ID dell''ultimo evento ricevuto in un header Last-Event-ID, così che il server riprenda il flusso senza buchi. La riconnessione WebSocket, invece, resta da scrivere.'
  - question: 'SSE può inviare dati binari?'
    answer: 'No – il flusso è testo UTF-8 per specifica; i payload binari vanno codificati, con circa un terzo di sovraccarico in dimensione. I WebSocket trasportano frame binari in modo nativo, cosa che conta per l''audio, i protocol buffer e tutto ciò che è già compatto.'
  - question: 'Che cosa usano le app di chat con l''IA per trasmettere le risposte?'
    answer: 'Server-Sent Events, quasi sempre: la generazione token per token è testo trasmesso in un solo senso, che è esattamente la forma di SSE – HTTP ordinario in uscita, nessuna negoziazione di upgrade, ripresa automatica. I WebSocket compaiono nei prodotti di IA solo quando il client deve interrompere o parlare a metà del flusso, come nelle interfacce vocali.'
  - question: 'Qual è l''ordine di ripiego per le funzionalità in tempo reale?'
    answer: 'Rilevare le capacità e degradare: WebSocket dove il percorso di rete li supporta, SSE dove serve solo il push dal server o dove gli upgrade falliscono, long polling come minimo comune denominatore. Le librerie di tempo reale mature negoziano questa scala automaticamente – una ragione in più per cui i socket grezzi si usano raramente nudi in produzione.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'Server-sent events — WHATWG HTML Living Standard'
    url: 'https://html.spec.whatwg.org/multipage/server-sent-events.html'
  - name: 'RFC 6455 — The WebSocket Protocol'
    url: 'https://datatracker.ietf.org/doc/html/rfc6455'
  - name: 'Using server-sent events — MDN Web Docs'
    url: 'https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events'
  - name: 'RFC 6202 — Known Issues with Long Polling and HTTP Streaming'
    url: 'https://datatracker.ietf.org/doc/html/rfc6202'
cta:
  title: 'Salta la decisione sul trasporto'
  text: 'Le Live Queries di Back4app consegnano gli aggiornamenti in tempo reale su una flotta di WebSocket gestita: sottoscrivi la query che hai già e lascia alla piattaforma connessioni, riconnessioni e fan-out.'
  linkText: 'Inizia gratis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-10-06'
translationKey: sse-vs-websockets-vs-polling
---

**Il polling è un modello pull in cui il client chiede in continuazione; SSE e WebSocket tengono aperta una connessione perché il server spinga in tempo reale.** Scegliere fra i tre si riduce in realtà a tre domande – in quale senso scorrono i dati, con quale frequenza cambiano e quale infrastruttura si trova in mezzo – e la risposta onesta cambia per singola funzionalità, non per applicazione.

## Punti chiave

| Domanda | Risposta |
| --- | --- |
| Short polling | Chiedere a intervallo fisso – semplice, compatibile con la cache, richieste in gran parte sprecate |
| Long polling | Il server trattiene la richiesta fino all'arrivo dei dati – push simulato su HTTP ordinario |
| SSE | Un flusso HTTP, eventi di testo server → client, riconnessione automatica integrata |
| WebSocket | Un socket, full-duplex, capace di binario – il protocollo resta in mano a chi sviluppa |
| La regola empirica | Senso unico → SSE · due sensi → WebSocket · cambiamenti rari → il polling basta |

## Il codice, affiancato

```js
// 1 · Short polling – chiedere a intervallo fisso
setInterval(async () => {
  const res = await fetch('/api/messages?since=' + lastId);
  render(await res.json());              // quasi sempre vuoto – header pagati comunque
}, 2000);

// 2 · Server-Sent Events – un flusso HTTP, il server spinge eventi di testo
const events = new EventSource('/api/stream');
events.onmessage = (e) => render(JSON.parse(e.data));   // si riconnette da solo

// 3 · WebSocket – un socket, entrambi i sensi
const ws = new WebSocket('wss://api.example.com/live');
ws.onmessage = (e) => render(JSON.parse(e.data));
ws.send(JSON.stringify({ type: 'typing' }));            // spinge anche il client
```

Ciò che la maggior parte delle applicazioni manda davvero in produzione – un livello di sottoscrizione che si prende il trasporto:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// The polling replacement: subscribe once, receive pushes
const query = new Parse.Query('Message');
query.equalTo('room', 'general');
const subscription = await query.subscribe();    // WebSocket under the hood
subscription.on('create', (msg) => render(msg)); // pushed, not polled
// subscription.unsubscribe() when the screen closes
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// The polling replacement: subscribe once, receive pushes
final liveQuery = LiveQuery();
final query = QueryBuilder<ParseObject>(ParseObject('Message'))
  ..whereEqualTo('room', 'general');
final subscription = await liveQuery.client.subscribe(query); // WebSocket under the hood
subscription.on(LiveQueryEvent.create, (msg) => render(msg)); // pushed, not polled
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// The polling replacement: subscribe once, receive pushes
let query = Message.query("room" == "general")
let subscription = try await query.subscribe() // WebSocket under the hood
subscription.handleEvent { _, event in
    if case .created(let msg) = event { render(msg) } // pushed, not polled
}
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// The polling replacement: subscribe once, receive pushes
val client = ParseLiveQueryClient.Factory.getClient()
val query = ParseQuery.getQuery<ParseObject>("Message")
query.whereEqualTo("room", "general")
val subscription = client.subscribe(query) // WebSocket under the hood
subscription.handleEvent(SubscriptionHandling.Event.CREATE) { _, msg ->
    render(msg) // pushed, not polled
}
```

## Come funziona ciascuna tecnica

**Lo short polling** è un `setInterval` attorno a un fetch: chiedere ogni *n* secondi se qualcosa è cambiato. Ogni ciclo paga una richiesta/risposta HTTP completa – header, autenticazione, instradamento – per sentirsi dire, quasi sempre, "ancora niente", e il ritardo medio di consegna vale metà dell'intervallo più un andata e ritorno.

**Il long polling** sposta l'attesa lato server: il client chiede, il server *tiene aperta la richiesta* fino all'arrivo dei dati o allo scadere di un timeout, il client richiede immediatamente. Approssima il push su HTTP semplicissimo – l'aggiramento dell'era Comet, con i suoi costi noti (andirivieni di riconnessioni, header per richiesta, cura nell'ordinamento) catalogati nella [RFC 6202](https://datatracker.ietf.org/doc/html/rfc6202).

**I Server-Sent Events** rendono permanente la risposta trattenuta: una risposta HTTP con `Content-Type: text/event-stream` che non termina mai, dentro la quale il server scrive eventi UTF-8 (campi `data:`, `event:`, `id:`, `retry:`, secondo lo [standard WHATWG](https://html.spec.whatwg.org/multipage/server-sent-events.html)). L'`EventSource` del browser lo consuma – e si riconnette automaticamente, riprendendo via `Last-Event-ID`.

**I WebSocket** abbandonano HTTP del tutto: un handshake fa l'upgrade della connessione (`101 Switching Protocols`, [RFC 6455](https://datatracker.ietf.org/doc/html/rfc6455)), dopodiché i due lati si scambiano frame di testo o binari con circa 2–14 byte di overhead, in full-duplex, finché qualcuno non chiude il socket. Capacità massima – e tutto ciò che sta sopra il frame (formato dei messaggi, conferme, riconnessione, ripresa) resta da progettare.

```mermaid
flowchart LR
  accTitle: Il pull del polling a confronto con il push di SSE e dei WebSocket
  accDescr: Con il polling il client chiede di continuo aggiornamenti al server e la maggior parte delle risposte è vuota. Con i Server-Sent Events il server spinge eventi verso il client su un unico flusso HTTP trattenuto. Con i WebSocket client e server si scambiano frame nei due sensi su un solo socket persistente.
  subgraph P["Polling – pull"]
    C1["Client"] -->|"chiedere ogni n s (quasi sempre vuoto)"| S1["Server"]
  end
  subgraph E["SSE – push"]
    S2["Server"] -->|"un flusso HTTP di eventi"| C2["Client<br/>(EventSource)"]
  end
  subgraph W["WebSocket – duplex"]
    C3["Client"] -->|"frame"| S3["Server"]
    S3 -->|"frame"| C3
  end
```

## SSE vs. WebSocket vs. long polling vs. short polling

| | Short polling | Long polling | SSE | WebSocket |
| --- | --- | --- | --- | --- |
| Direzione | Pull | Push simulato | Server → client | Full-duplex |
| Protocollo | HTTP ordinario | HTTP ordinario | Flusso HTTP ordinario | Protocollo proprio dopo l'upgrade |
| Latenza di consegna | intervallo/2 + RTT | ~RTT | ~RTT | ~RTT |
| Payload | Qualsiasi | Qualsiasi | Solo testo UTF-8 | Testo + binario |
| Riconnessione auto | Banale (poll successivo) | Ciclo di nuova richiesta | **Integrata + Last-Event-ID** | Resta da scrivere |
| Attriti con proxy/firewall | Nessuno | Bassi | Bassi (attenzione al buffering) | L'upgrade può essere rimosso |
| Stato sul server | Nessuno | Richieste trattenute | Stream aperti | Socket appuntati |
| Complessità | Banale | Moderata | Bassa | La più alta |
| Terreno ideale | Cambiamenti rari | Ripiego legacy | Feed, notifiche, stream di IA | Chat, giochi, collaborazione |

## Quanto costa il polling? Il conto dell'overhead

Il confronto che nessuna pagina di classifica fa – 1.000 client con un poll da 2 secondi contro gli stessi 1.000 in push:

```text
1.000 client, polling da 2 s              1.000 client, push
→ 500 richieste/secondo in continuo       → 0 richieste a riposo
→ ~800 B di header per ciclo              → framing degli eventi SSE ~5 B
→ ~0,4 MB/s di pura tassa di header       → overhead del frame WebSocket 2–14 B
→ quasi ogni risposta è vuota             → i byte scorrono solo se ci sono dati
→ ritardo medio di consegna: 1 s + RTT    → ritardo di consegna: ~RTT
```

La lezione taglia in due sensi. Il push vince largamente quando gli aggiornamenti sono frequenti e la latenza conta. Ma se i dati cambiano ogni ora, quelle 500 richieste al secondo non si materializzano mai – un poll gentile (o una ricarica al ritorno del focus) è compatibile con la cache, si debugga con curl, va d'accordo con il serverless ed è privo di stato di connessione. Liquidare il polling in blocco è moda, non ingegneria.

## La riconnessione: il differenziatore silenzioso

Le connessioni cadono – passaggi di cella, coperchi di portatili, timeout di inattività dei proxy (spesso 30–120 s, ed è per questo che i flussi SSE inviano commenti di keep-alive e i WebSocket si scambiano frame ping/pong). Ciò che accade dopo separa i trasporti. Il contratto di SSE se ne occupa: il browser ritenta con il ritardo `retry` fissato dal server e presenta `Last-Event-ID`, così un server che conserva un breve buffer di eventi riprende il flusso senza buchi. Un WebSocket grezzo, invece, si limita a chiudersi: riconnessione con backoff esponenziale, recupero dei messaggi perduti e protocollo di ripresa sono tutto codice applicativo – la voce di costo più sottovalutata di "usiamo i WebSocket e via". In entrambi i casi un client offline per qualche minuto ha bisogno di *recuperare* (rieseguendo la query di base), non solo di riconnettersi: i trasporti push consegnano delta, e i delta presuppongono un punto di riferimento.

## Perché la chat con l'IA passa da SSE

L'output di un modello token per token è il carico perfetto per SSE: rigorosamente a senso unico, testuale, a raffiche, su HTTP ordinario che ogni proxy e ogni CDN capisce, con una semantica di ripresa per le generazioni interrotte. È per questo che le API di LLM trasmettono in massa i completamenti come `text/event-stream` – e per questo il pattern vale la pena di conoscerlo oltre i chatbot: feed di progresso, log di build e dashboard condividono la stessa forma. I WebSocket entrano nei prodotti di IA al livello della voce, dove l'utente interrompe a metà del flusso: nell'istante in cui il client deve rispondere, la tassa del duplex compra qualcosa.

## Scalare il push: perché lo stato conta

Polling e SSE sono HTTP ordinario per un load balancer; qualsiasi server può rispondere a qualsiasi richiesta (SSE trattiene un flusso ma conserva la semantica HTTP, e gli servono soltanto proxy senza buffering). I WebSocket, invece, sono *stato*: ogni socket appunta un client a un processo, quindi la scalabilità orizzontale significa bilanciamento consapevole delle connessioni, svuotamento durante i deployment e un backplane [pub/sub](/glossary/pub-sub-pattern/) (spesso Redis) perché un messaggio pubblicato sul server A raggiunga i socket tenuti dal server B. Su HTTP/1.1, SSE ha la sua insidia celebre – sei connessioni per origine *condivise fra le schede* ([l'avvertimento di MDN](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)) – mandata in pensione da HTTP/2, dove gli stream si multiplexano su una sola connessione. Niente di tutto questo è esotico; tutto questo spiega perché esistono i livelli gestiti di tempo reale.

## Casi d'uso tipici

- **Feed di notifiche e ticker** – senso unico, testo, frequenti: il terreno di casa di SSE.
- **Streaming delle risposte di IA** – l'uso di punta di SSE oggi; un solo senso, testo di token, ripresa in caso di caduta.
- **Chat e collaborazione** – i messaggi scorrono nei due sensi con bassa latenza: [WebSocket](/glossary/it/websockets/), di solito tramite un livello gestito.
- **Dashboard in diretta** – push dal server di risultati di query; in pratica una sottoscrizione [live query](/glossary/it/live-queries-tempo-reale/) più che un trasporto scritto a mano.
- **Dati che cambiano lentamente** – un inventario aggiornato ogni ora, schermate di impostazioni: polling o ricarica al ritorno del focus, onestamente.

## Quale trasporto scegliere? Matrice decisionale

| La situazione | Scegliere |
| --- | --- |
| Solo server → client (feed, stream, progresso) | SSE |
| Client e server inviano entrambi in tempo reale | WebSocket |
| Aggiornamenti più rari di qualche minuto | Short polling / ricarica al ritorno del focus |
| Proxy ostili, infrastruttura legacy | Long polling come ripiego |
| Payload binari o ad alta frequenza | WebSocket |
| Piattaforma serverless, timeout delle funzioni | Polling o SSE tramite host capaci di streaming |
| "Serve solo avere dati in diretta sullo schermo" | Un livello di live queries che si prende il trasporto |

## Limiti e trade-off

- **SSE è solo testo e a senso unico.** Il binario va codificato; qualsiasi chiacchiera dal client al server passa da richieste HTTP separate – perfetto per le conferme, sbagliato per la chat.
- **I WebSocket mettono chi sviluppa nel mestiere dei protocolli.** Framing, conferme, riconnessione, ripresa, backpressure: il trasporto è facile, il contratto che ci sta sopra è il lavoro vero.
- **La semplicità del polling nasconde un pavimento di latenza.** Nessuna regolazione sfugge al ritardo medio di intervallo/2; accorciare l'intervallo si limita a ricomprare la tassa degli header.
- **Il long polling è il peggio dei due su larga scala.** Le richieste trattenute consumano capacità del server come il push, pagando però un overhead di riconnessione per messaggio come il pull – ed è per questo che sopravvive solo come piolo di ripiego.
- **Tutti i trasporti push richiedono la collaborazione dei proxy.** Il buffering degli stream rompe SSE in silenzio; header di upgrade rimossi rompono i WebSocket – conviene provare attraverso l'infrastruttura reale, non su localhost.

## I trasporti in tempo reale 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 decisione sul trasporto viene in gran parte assorbita dalle [Live Queries](/glossary/it/live-queries-tempo-reale/): le schede di codice qui sopra sottoscrivono una query e ricevono eventi spinti su una flotta di WebSocket che la piattaforma fa girare – connessioni, riconnessioni, verifiche dei permessi e fan-out fra server inclusi – così che "SSE o WebSocket?" diventi un dettaglio di implementazione che si eredita invece di un'infrastruttura da costruire. Dove una cadenza più tranquilla va davvero bene, la stessa query gira come un semplice fetch con il ritmo che si preferisce; fare polling su una query Parse e sottoscriverla distano una riga, il che rende il trasporto giusto per ogni funzionalità un refactoring e non una riscrittura.
