Issue 10011 · Sistemi distribuiti
Inbox Pattern e consumer idempotenti
Come evitare effetti di business duplicati quando retry e redelivery sono normali, non eccezioni
· 5 min

Obiettivo
Progettare consumer di messaggi in modo che retry, consegne duplicate e fallimenti parziali non producano effetti di business duplicati e indesiderati.
Come ragionare sul problema
In un sistema distribuito, il punto non è chiedersi se arriveranno duplicati, ma quando. Un consumer robusto non assume la consegna exactly-once a livello applicativo: deve invece riconoscere un messaggio già visto, decidere se l’effetto di business è già stato applicato e rendere esplicita la semantica di idempotenzaGlossarioIdempotenzaLa proprietà per cui ripetere un’operazione non produce effetti aggiuntivi indesiderati.Apri la voce completa. L’Inbox Pattern è utile quando il consumer deve separare due responsabilità: tracciare l’arrivo del messaggio e applicare l’azione di business. In pratica, prima di modificare lo stato, il consumer registra l’identificativo univoco del messaggio in un’area locale o in una tabella di inbox. Se l’ID è già presente, il consumer evita di ripetere l’effetto. Il punto architetturale importante è stabilire cosa rende un messaggio univoco: messageId, businessKey, eventoGlossarioEventoUna dichiarazione durevole che qualcosa di significativo è già accaduto.Apri la voce completa sorgente o una combinazione dei tre. Questa scelta non è solo tecnica, perché determina quali duplicati verranno filtrati e quali casi reali rischiano di essere scambiati per retryGlossarioRetryUn nuovo tentativo eseguito dopo un fallimento che potrebbe essere transitorio.Apri la voce completa. • Usa un identificativo stabile e condiviso per distinguere i duplicati veri dai messaggi diversi ma simili. • Rendi atomica, quando possibile, la registrazione dell’inbox e l’aggiornamento di business. • Definisci esplicitamente la finestra temporale di conservazione dell’inbox in base a retry, retention e audit.
I trade-off da rendere visibili
L’Inbox Pattern riduce il rischio di doppie esecuzioni, ma introduce costo operativo e complessità. Più controlli aggiungi, più aumentano letture/scritture sul datastore, necessità di pulizia dei record storici e attenzione ai casi di concorrenza. Il vantaggio è chiaro: proteggi ordini, pagamenti, notifiche o workflow da effetti duplicati. Il costo è altrettanto reale: il consumer diventa più lento, devi gestire lo stato dell’inbox e devi chiarire che il broker da solo non garantisce la correttezza di business. C’è anche un trade-offGlossarioTrade-offUno scambio in cui migliorare un risultato ne indebolisce o ne rende più costoso un altro.Apri la voce completa di progettazione: se l’idempotenza viene spostata troppo in basso, rischi di mascherare errori di dominioGlossarioDominioLa parte del mondo reale, del business o dell’organizzazione che un sistema deve supportare.Apri la voce completa; se viene lasciata troppo in alto, ogni consumer reimplementa logiche simili in modo incoerente. La decisione migliore di solito è centralizzare il pattern dove il dominio lo richiede davvero, non ovunque per principio. • Più robustezza contro i duplicati, ma più latenza e persistenza aggiuntiva. • Più controllo applicativo, ma maggiore responsabilità del team sul lifecycle dei record di inbox. • Più chiarezza semantica sul business, ma più lavoro per progettare chiavi, retention e osservabilitàGlossarioOsservabilitàLa capacità di comprendere il comportamento di un sistema a partire dai segnali che produce.Apri la voce completa.
Un caso realistico in azienda
Immagina una piattaforma retail che riceve eventi di conferma pagamento da un broker e aggiorna lo stato dell’ordine. In alcuni giorni il team osserva retry dal consumer dopo timeoutGlossarioTimeoutUn limite definito a quanto un’operazione attende prima di considerare il tentativo non riuscito.Apri la voce completa verso il database. Senza protezione, lo stesso evento può confermare due volte un ordine, attivare due notifiche al cliente o avviare due volte un workflow di fulfillment. Con l’Inbox Pattern, il consumer salva l’eventId appena riceve il messaggio. Se il retry ripresenta lo stesso ID, il consumer riconosce che il processing è già stato fatto e termina senza ripetere l’effetto di business. A livello di meeting di design, il team deve chiarire anche cosa succede se il messaggio arriva dopo che l’ordine è già stato annullato: in quel caso il messaggio è duplicato dal punto di vista tecnico, ma non necessariamente innocuo dal punto di vista di dominio. Questa distinzione evita discussioni ambigue tra team applicativo, operations e architettura: non basta prevenire il duplicate delivery, bisogna decidere quale stato di business ha priorità quando il tempo di arrivo cambia il significato del messaggio. • Rete, timeout e retry possono trasformare un singolo evento di pagamento in più consegne osservabili. • Il consumer deve distinguere duplicate delivery da eventi tardivi ma validi nel dominio. • Le regole di dominio devono dire quando ignorare, compensare o rielaborare un messaggio.
Per approfondire
Riferimenti esterni autorevoli per approfondire il pattern e le implicazioni dei consumer idempotenti. • Idempotent Consumer - microservices.io - https://microservices.io/patterns/communication-style/idempotent-consumer.html • Patterns of Enterprise Application Architecture - Martin Fowler - https://martinfowler.com/eaaCatalog/idempotentReceiver.html