---
term: 'Pattern Pub/Sub (publish-subscribe)'
seoTitle: 'Pattern pub/sub: topic, broker e garanzie di consegna'
headline: 'Che cos''è il pattern pub/sub (publish-subscribe)?'
slug: pattern-pub-sub
category: api-realtime
shortDefinition: 'Il pub/sub è un pattern di messaggistica in cui i publisher inviano messaggi a dei topic su un broker e ogni subscriber di un topic ne riceve una copia.'
relatedTerms:
  - event-driven-architecture
  - websockets-real-time-sync
  - real-time-live-queries
  - sse-vs-websockets-vs-polling
contrastsWith:
  - webhooks
aboutTerms:
  - 'Publisher'
  - 'Subscriber'
  - 'Topic'
  - 'Message Broker'
faq:
  - question: 'Che cos''è il pub/sub in parole semplici?'
    answer: 'Un pattern di messaggistica in cui i mittenti (i publisher) pubblicano messaggi su topic con un nome ospitati da un broker, e ogni componente che si è sottoscritto a quel topic riceve la propria copia – publisher e subscriber non si conoscono mai. Vale l''immagine della radio: la stazione trasmette su una frequenza; chi si sintonizza, ascolta.'
  - question: 'Qual è la differenza tra il pub/sub e una coda di messaggi?'
    answer: 'Una coda ripartisce il lavoro; il pub/sub lo duplica. In una coda ogni messaggio viene consumato da un solo worker – lo strumento per distribuire job su un pool. Nel pub/sub ogni subscriber del topic riceve una copia – lo strumento per diffondere eventi verso parti interessate in modo indipendente l''una dall''altra.'
  - question: 'Qual è la differenza tra il pub/sub e il pattern observer?'
    answer: 'L''observer vive dentro un solo processo: il soggetto conserva riferimenti diretti ai propri observer e di solito li chiama in modo sincrono. Il pub/sub intercala un broker fra le parti, le disaccoppia completamente, rende lo scambio tipicamente asincrono e consente loro di vivere in processi, linguaggi e deployment diversi. Uno è un design pattern interno a un''app; l''altro è un''architettura fra sistemi.'
  - question: 'Che cos''è un topic nel pub/sub?'
    answer: 'Un canale logico con un nome che categorizza i messaggi: i publisher si rivolgono al topic e il broker consegna ogni messaggio a tutti i subscriber di quel topic. Il filtraggio può essere per topic (sottoscrizione per nome, spesso gerarchica – orders.*) oppure per contenuto, con il broker che confronta gli attributi dei messaggi.'
  - question: 'Quali garanzie di consegna offre il pub/sub?'
    answer: 'Tre livelli. At-most-once: fire-and-forget – rapido, qualche messaggio può perdersi. At-least-once: retry fino alla conferma – la scelta predefinita più comune, che produce duplicati occasionali. Exactly-once: deduplicazione più coordinamento – costoso, vincolato e impossibile da garantire da un capo all''altro nel caso generale. La posizione pragmatica: consegna at-least-once con handler idempotenti.'
  - question: 'Il pub/sub garantisce l''ordine dei messaggi?'
    answer: 'Non per impostazione predefinita – i messaggi partono in fan-out verso subscriber paralleli, e un ordine globale combatte il parallelismo. I broker sanno ordinare dentro una partizione o una chiave di ordinamento, al prezzo del throughput. Una progettazione robusta presuppone un ordine solo dove è configurato in modo esplicito e scrive handler che tollerano gli arrivi fuori sequenza.'
  - question: 'Kafka è pub/sub?'
    answer: 'Sì, con una sfumatura: Apache Kafka implementa la semantica publish-subscribe sopra un commit log partizionato, durevole e riproducibile (replay). Dentro un consumer group si comporta come una coda (ogni messaggio va a un solo membro); fra gruppi diversi si comporta come pub/sub (ogni gruppo riceve una copia) – ed è per questo che di solito si parla di event streaming.'
  - question: 'Quando conviene evitare il pub/sub?'
    answer: 'Quando chi chiama ha bisogno di una risposta immediata (richiesta-risposta), quando alcune operazioni devono essere atomiche fra produttore e consumatori (un broker non può partecipare a una transazione – si veda il pattern saga), quando serve un ordine globale stretto, oppure quando il sistema è abbastanza piccolo perché un broker aggiunga più superficie operativa di quanta ne tolga.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'Publish-Subscribe Channel — Enterprise Integration Patterns'
    url: 'https://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html'
  - name: 'MQTT 5.0 specification — OASIS'
    url: 'https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html'
  - name: 'Apache Kafka documentation — design'
    url: 'https://kafka.apache.org/documentation/#design'
  - name: 'What do you mean by "Event-Driven"? — Martin Fowler'
    url: 'https://martinfowler.com/articles/201701-event-driven.html'
cta:
  title: 'Pubblica salvando, sottoscrivi interrogando'
  text: 'Le Live Queries di Back4app sono pub/sub al bordo: qualsiasi client si sottoscrive a una query come se fosse un topic e ogni tua scrittura viene pubblicata verso tutti i subscriber interessati – broker, fan-out e permessi li gestisce la piattaforma.'
  linkText: 'Inizia gratis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-10-19'
translationKey: pub-sub-pattern
---

**Il pub/sub è un pattern di messaggistica in cui i publisher inviano messaggi a dei topic su un broker e ogni subscriber di un topic ne riceve una copia.** Tutto il suo valore sta in ciò che le parti *non* sanno: i publisher non scoprono mai chi ascolta, i subscriber non scoprono mai chi ha inviato – l'indirezione del broker li disaccoppia nello spazio (sistemi diversi), nel tempo (i subscriber possono essere offline) e nella sincronizzazione (la pubblicazione restituisce subito il controllo). Si aggiungono subscriber senza toccare i publisher: è il superpotere discreto del pattern.

## Punti chiave

| Domanda | Risposta |
| --- | --- |
| Gli attori | Publisher → messaggio → topic → broker → subscriber (ognuno riceve una copia) |
| vs. una coda | Una coda *ripartisce* il lavoro verso un solo consumatore; il pub/sub lo *duplica* verso tutti |
| vs. observer | L'observer è interno al processo e sincrono; il pub/sub passa da un broker ed è asincrono |
| La posizione predefinita | Consegna at-least-once + handler idempotenti |
| Le clausole in piccolo | Nessuna risposta, nessun ordine predefinito, nessuna transazione atomica attraverso il broker |

## Il pattern in codice

Qualunque API pub/sub si riduce a due verbi, indipendentemente dal broker:

```js
// Subscriber – dichiarano interesse per un topic
broker.subscribe('orders.paid', (msg) => fulfill(msg));   // servizio A
broker.subscribe('orders.paid', (msg) => notifyUser(msg)); // servizio B – copia propria

// Publisher – fire and forget
broker.publish('orders.paid', { orderId: 'o-1187' });
// Il publisher non scopre mai chi l'ha ricevuto – né se qualcuno l'ha ricevuto.
```

La stessa forma sul lato client, dove una sottoscrizione live query fa da topic e una scrittura sul database fa da pubblicazione:

**JavaScript:**

```javascript
// JavaScript / Node.js — Back4app JS SDK
// Pub/sub at the edge: live queries subscribe, saves publish
// Subscriber — register interest in a topic
const topic = new Parse.Query('Event');
topic.equalTo('topic', 'orders');
const sub = await topic.subscribe();
sub.on('create', (event) => handle(event.get('payload')));

// Publisher — fire and forget; no knowledge of subscribers
const event = new Parse.Object('Event');
event.set('topic', 'orders');
event.set('payload', { orderId: 'o-1187', status: 'paid' });
await event.save();
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// Pub/sub at the edge: live queries subscribe, saves publish
// Subscriber — register interest in a topic
final liveQuery = LiveQuery();
final topic = QueryBuilder<ParseObject>(ParseObject('Event'))
  ..whereEqualTo('topic', 'orders');
final sub = await liveQuery.client.subscribe(topic);
sub.on(LiveQueryEvent.create, (event) => handle(event.get('payload')));

// Publisher — fire and forget; no knowledge of subscribers
final event = ParseObject('Event')
  ..set('topic', 'orders')
  ..set('payload', {'orderId': 'o-1187', 'status': 'paid'});
await event.save();
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// Pub/sub at the edge: live queries subscribe, saves publish
// Subscriber — register interest in a topic
let topic = Event.query("topic" == "orders")
let sub = try await topic.subscribe()
sub.handleEvent { _, e in
    if case .created(let event) = e { handle(event.payload) }
}

// Publisher — fire and forget; no knowledge of subscribers
var event = Event()
event.topic = "orders"
event.payload = ["orderId": "o-1187", "status": "paid"]
try await event.save()
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// Pub/sub at the edge: live queries subscribe, saves publish
// Subscriber — register interest in a topic
val client = ParseLiveQueryClient.Factory.getClient()
val topic = ParseQuery.getQuery<ParseObject>("Event")
topic.whereEqualTo("topic", "orders")
val sub = client.subscribe(topic)
sub.handleEvent(SubscriptionHandling.Event.CREATE) { _, event ->
    handle(event.getJSONObject("payload"))
}

// Publisher — fire and forget; no knowledge of subscribers
val event = ParseObject("Event")
event.put("topic", "orders")
event.put("payload", JSONObject(mapOf("orderId" to "o-1187", "status" to "paid")))
event.save()
```

## Come funziona il pub/sub

```mermaid
flowchart LR
  accTitle: Flusso di messaggi publish-subscribe attraverso un broker
  accDescr: Un publisher invia un messaggio a un topic con un nome ospitato da un broker di messaggi. Il broker confronta il topic con le sottoscrizioni registrate e consegna una copia indipendente del messaggio a ogni subscriber, che ne conferma l'elaborazione separatamente.
  P["Publisher<br/>(fire & forget)"] -->|"publish(orders.paid, msg)"| T["Broker<br/>topic: orders.paid"]
  T -->|"copia 1"| S1["Subscriber A<br/>evasione ordini"]
  T -->|"copia 2"| S2["Subscriber B<br/>notifiche"]
  T -->|"copia 3"| S3["Subscriber C<br/>analytics"]
```

Il broker svolge quattro compiti: **accettare** le pubblicazioni e restituire subito il controllo; **far corrispondere** ogni messaggio alle sottoscrizioni (per nome del topic, in modo gerarchico – `orders.*` – oppure per attributi di contenuto); **consegnare** una copia indipendente a ogni subscriber, con retry secondo il suo livello di garanzia; e **conservare** i messaggi per i subscriber offline dove la durabilità è configurata – il disaccoppiamento temporale che permette a un servizio rilasciato a mezzogiorno di recuperare ciò che ha perso. Una nota di vocabolario che merita una frase: il *messaggio* è la busta; l'*evento* – "questo è accaduto", al passato – è ciò che il pub/sub trasporta di solito, e il fatto che porti il solo accaduto oppure lo stato completo è la distinzione di [Fowler](https://martinfowler.com/articles/201701-event-driven.html) fra event notification ed event-carried state transfer.

## Pub/sub vs. code di messaggi vs. pattern observer

Le due confusioni, risolte in una tabella:

| | Pub/sub | Coda di messaggi | Observer |
| --- | --- | --- | --- |
| Consegna | Ogni subscriber riceve una copia | Un solo worker consuma ciascun messaggio | Il soggetto chiama ogni observer |
| Ruolo | Diffondere eventi | Ripartire il lavoro | Reagire a uno stato dentro il processo |
| Accoppiamento | Nessuno – mediato dal broker | Nessuno – mediato dalla coda | Riferimenti diretti fra oggetti |
| Tempi | Asincrono | Asincrono | Di solito sincrono |
| Confine | Fra processi e sistemi | Fra worker | Dentro un solo processo |
| Forma canonica | 1 evento → N reazioni | N job → M worker | 1 oggetto → i suoi listener |

La formula che sopravvive alla riunione: **una coda ripartisce il lavoro; il pub/sub lo duplica.** E l'observer non è un "pub/sub in piccolo" – l'indirezione del broker è esattamente ciò che all'observer manca, ed è per questo che trasformare un observer in pub/sub è un cambio di architettura, non una rinominazione. In pratica i broker offrono entrambe le forme: i consumer group trasformano un topic in una coda per gruppo (la mossa distintiva di [Kafka](https://kafka.apache.org/documentation/#design)), gli exchange fanout trasformano un sistema di code in pub/sub.

## Garanzie di consegna: at-most-once vs. at-least-once vs. exactly-once

| Garanzia | Modalità di guasto | Costo | L'handler deve | Sceglierla quando |
| --- | --- | --- | --- | --- |
| At-most-once | I messaggi possono svanire | Il più economico, il più rapido | Tollerare i buchi | Dati effimeri: presenza, ticker, metriche |
| At-least-once | Arrivano duplicati | Ack + retry | **Essere idempotente** | È la scelta predefinita per gli eventi di business |
| Exactly-once | Vincolato, complesso | Deduplicazione + coordinamento | Restare idempotente | Percorsi ristretti in cui il broker lo consente |

I livelli QoS 0/1/2 di [MQTT](https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html) corrispondono esattamente a questi tre – una conferma netta che la tricotomia è fondamentale e non un argomento di marketing. La verità di chi progetta: l'exactly-once da un capo all'altro è inarrivabile nel caso generale (il problema dei due generali con il distintivo del broker); i sistemi che lo annunciano combinano consegna at-least-once e deduplicazione. Per questo il vero contratto del pattern si scrive nel proprio handler: **at-least-once + idempotenza** – deduplicare su un ID del messaggio, usare upsert con chiave sull'entità oppure verificare la versione prima di applicare – trasforma i duplicati da bug in no-op.

## Ordine, dead letter e progettazione dei topic

Tre realtà operative che i diagrammi introduttivi saltano. **L'ordine:** il fan-out verso consumatori paralleli non ha ordine globale; i broker lo ripristinano per partizione o per chiave di ordinamento, al prezzo del parallelismo – conviene progettare gli handler perché applichino gli eventi per ID dell'entità e per versione, non per ordine di arrivo, e il problema si dissolve in buona parte. **I messaggi avvelenati:** un messaggio la cui elaborazione solleva sempre un'eccezione viene ritentato all'infinito in at-least-once; conviene limitare i tentativi di consegna e instradare i fallimenti verso una **dead letter queue** per il triage, altrimenti un solo evento difettoso blocca il topic. **La progettazione dei topic:** nomi gerarchici (`orders.paid`, `orders.refunded`, jolly `orders.*`), granularità al livello su cui i subscriber differiscono davvero, ed evoluzione additiva degli schemi dei messaggi – i subscriber ignorano i campi sconosciuti; le modifiche incompatibili ricevono un nuovo topic versionato (`orders.v2`) con una finestra di migrazione, esattamente come una versione di API.

## Casi d'uso tipici

- **Integrazione di microservizi** – servizi di team diversi che reagiscono agli [eventi](/glossary/it/architettura-disaccoppiata/) degli altri senza chiamate dirette né calendari di deployment condivisi.
- **Funzionalità in tempo reale lato client** – fan-out di chat, dashboard in diretta, [presenza](/glossary/it/presenza-stato-online/): pub/sub su WebSocket lato client.
- **Telemetria IoT** – migliaia di dispositivi che pubblicano via MQTT; consumatori che vanno dagli avvisi all'analytics e si sottoscrivono in modo indipendente.
- **Invalidazione della cache e replica** – una scrittura pubblicata, e ogni cache e ogni replica avvisate.
- **Pipeline di elaborazione in parallelo** – un evento che avvia insieme evasione, notifica e analytics, ognuna con i propri tempi.

## Conviene usare il pub/sub? Matrice decisionale

| Il pub/sub va bene quando… | Meglio qualcos'altro quando… |
| --- | --- |
| Un evento interessa più consumatori indipendenti | C'è un solo consumatore: una coda, o una semplice chiamata |
| Produttori e consumatori rilasciano in modo indipendente | Chi chiama ha bisogno della risposta subito → richiesta-risposta |
| L'eventual consistency (coerenza finale) è accettabile | Serve atomicità fra le parti → transazioni o saga |
| I subscriber vanno e vengono col tempo | Un ordine globale stretto non è negoziabile |
| Un carico a picchi va ammortizzato fra sistemi | Tutto il sistema sta in un solo processo → observer |

## Limiti e trade-off

- **Il debug attraversa un broker.** "Chi ha consumato questo, e perché è fallito?" esige ID di correlazione e tracing; il disaccoppiamento che libera i team nasconde anche la causalità.
- **Nessuna risposta, per progetto.** I workflow che hanno bisogno di risposte devono modellarle come messaggi ulteriori – latenza in più e macchine a stati dove bastava una chiamata di funzione.
- **Il broker è infrastruttura.** Disponibilità, capacità, sicurezza e politiche di conservazione del livello di messaggistica diventano lavoro di piattaforma; un broker fuori servizio moltiplica gli incidenti.
- **La cecità del publisher è un'arma a doppio taglio.** I publisher non vedono la salute dei subscriber; un consumatore che fallisce in silenzio perde dati se non esiste un monitoring delle dead letter.
- **Le garanzie costano throughput.** Le chiavi di ordinamento serializzano, l'exactly-once coordina, la durabilità persiste – ogni rafforzamento della semantica si paga in prestazioni; conviene comprare solo ciò di cui i dati hanno davvero bisogno.

## Il pub/sub 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. Il pattern compare qui sul lato client: le [Live Queries](/glossary/it/live-queries-tempo-reale/) sono pub/sub in cui *la query è il topic* – i subscriber registrano un predicato, e qualsiasi scrittura che corrisponda a quel predicato viene pubblicata verso ogni subscriber su una flotta gestita di [WebSocket](/glossary/it/websockets/), con i permessi verificati per singolo subscriber e il fan-out gestito dalla piattaforma, come nelle schede di codice qui sopra. Le reazioni lato server si compongono allo stesso modo: i trigger Cloud Code si sottoscrivono alle modifiche dei dati (`afterSave` come sottoscrizione a un topic, nello spirito) e le funzioni pianificate smaltiscono il lavoro pubblicato sotto forma di righe. Per lo streaming intenso fra servizi la scelta resta un broker dedicato come Kafka o RabbitMQ – ma per i casi di prodotto più comuni la diffusione a ogni cambiamento arriva insieme al backend.
