Gli abbonamenti ricorrenti sono il modello di monetizzazione preferito per app e SaaS perché generano ricavi prevedibili e migliorano il lifetime value del cliente. Ma implementare un sistema di billing ricorrente ben fatto è più complesso di quanto sembri. In questa guida condividiamo i pattern architetturali che usiamo in Soamee per costruire sistemi di abbonamento robusti in produzione.
Perché l’implementazione conta più di quanto pensi
La differenza tra un sistema di abbonamenti mediocre e uno eccellente può rappresentare il 20-30% del tuo MRR. Un buon dunning (gestione dei pagamenti falliti) può recuperare il 40-60% delle transazioni che inizialmente falliscono. Un trial ben progettato può convertire l’80-95% degli utenti che lo iniziano. E prorrazioni corrette evitano dispute con i clienti e perdite per addebiti errati.
Abbiamo visto startup perdere migliaia di euro al mese per implementazioni naive: retry di pagamento tutti alla stessa ora saturando la coda, prorrazioni che non tengono conto dei giorni reali del mese, trial che scadono senza notificare l’utente, e cancellazioni che non liberano correttamente i permessi del piano.
Architettura di un sistema di abbonamenti
Componenti principali
Un sistema di abbonamenti completo ha questi componenti:
- Subscription Engine: gestisce lo stato degli abbonamenti (active, trialing, past_due, canceled, paused).
- Billing Engine: calcola gli importi da addebitare, prorrazioni e genera fatture.
- Payment Processor: esegue gli addebiti (Stripe, Redsys, RevenueCat).
- Dunning System: gestisce i retry di pagamenti falliti e la comunicazione all’utente.
- Entitlement System: controlla quali funzionalità ha disponibili ogni utente in base al suo piano.
- Analytics: metriche di MRR, churn, LTV, conversione del trial.
Pattern di stati
Il ciclo di vita di un abbonamento segue questa macchina a stati:
[trialing] → [active] → [past_due] → [canceled]
↓ ↓ ↓
[canceled] [paused] [active] (se il pagamento viene recuperato)
Ogni transizione di stato deve:
- Aggiornare i permessi dell’utente (entitlements).
- Inviare la comunicazione adeguata (email, push notification).
- Registrare l’evento per l’analytics.
- Eseguire la logica di billing (addebitare, smettere di addebitare, prorare).
Opzione 1: Stripe Billing
Stripe Billing è la nostra raccomandazione predefinita per gli abbonamenti web. Gestisce la complessità del billing ricorrente e ti permette di concentrarti sul tuo prodotto.
Integrazione di base
L’integrazione minima con Stripe Billing prevede:
- Creare prodotti e piani in Stripe (via API o dashboard).
- Checkout Session per consentire all’utente di abbonarsi con un flusso di pagamento hosted o embeddato.
- Webhook per sincronizzare lo stato dell’abbonamento con il tuo database.
- Customer Portal per consentire all’utente di gestire il proprio abbonamento (cambiare piano, cancellare, aggiornare il pagamento).
I webhook critici da gestire:
customer.subscription.created: nuovo abbonamento creato.customer.subscription.updated: cambio di piano, stato o periodo.customer.subscription.deleted: abbonamento cancellato definitivamente.invoice.paid: pagamento riuscito, attivare/rinnovare l’accesso.invoice.payment_failed: pagamento fallito, avviare il dunning.customer.subscription.trial_will_end: trial in scadenza (3 giorni prima).
Gestione dei trial
Stripe supporta i trial nativamente. Configurazioni che raccomandiamo:
- Trial senza carta: più volume di trial ma minore conversione. Utile per prodotti con effetto rete dove hai bisogno di massa critica.
- Trial con carta: meno volume ma maggiore conversione (l’utente ha già l’intenzione di pagare). La nostra raccomandazione predefinita.
- Durata: 7-14 giorni è lo standard. GolfyApp usa 7 giorni con risultati di conversione del 95%.
La chiave della conversione durante il trial è l’attivazione. Se l’utente sperimenta il valore core del prodotto durante il trial, convertirà. La nostra strategia:
- Giorno 0: email di benvenuto con guida di avvio rapido.
- Giorno 1-2: se non ha usato la funzionalità principale, email con tutorial specifico.
- Giorno 5 (trial di 7): promemoria che il trial termina tra 2 giorni + riepilogo del valore ottenuto.
- Giorno 6: ultimo promemoria con offerta speciale se converte oggi.
Prorrazioni
Stripe calcola le prorrazioni automaticamente quando un utente cambia piano a metà ciclo. Ci sono tre strategie:
create_prorations(default): addebita/accredita la differenza proporzionale. Se l’utente passa dal Piano Base (10 EUR/mese) al Piano Pro (30 EUR/mese) a metà mese, vengono addebitati 10 EUR aggiuntivi per i 15 giorni rimanenti.none: nessuna prorrazione. Il nuovo piano entra in vigore nel prossimo ciclo.always_invoice: generare fattura immediata per la differenza.
Dunning
Stripe ha Smart Retries che usa ML per decidere quando riprovare un pagamento fallito. Integriamo con:
- Email automatica all’utente quando un pagamento fallisce con link per aggiornare il metodo di pagamento.
- 3 retry nei successivi 7 giorni con orari variabili.
- Se dopo 3 tentativi continua a fallire, contrassegnare come
past_duee notificare che il servizio verrà sospeso tra 3 giorni. - Dopo 10 giorni senza pagamento, cancellare l’abbonamento.
Questa configurazione ci permette di recuperare il 50-60% dei pagamenti falliti.
Opzione 2: RevenueCat per app mobili
Se la tua app vive su iOS e/o Android, gli abbonamenti in-app hanno le loro regole. Apple e Google gestiscono gli addebiti, ma hai bisogno di un backend che unifichi lo stato.
Perché RevenueCat
- Un SDK, due store: astrae le differenze tra App Store Connect e Google Play Billing.
- Validazione server-side: valida i receipt automaticamente senza che il tuo backend tocchi le API di Apple/Google.
- Webhook unificati: un unico endpoint riceve eventi da entrambi gli store.
- Analytics: metriche di abbonamento unificate (MRR, churn, trial conversion) tra iOS e Android.
- Esperimenti: A/B testing di pricing e paywall senza pubblicare una nuova versione.
Integrazione con RevenueCat
- SDK nell’app: configurare l’SDK di RevenueCat (Swift, Kotlin, React Native, Flutter).
- Prodotti negli store: creare prodotti di abbonamento in App Store Connect e Google Play Console.
- Mapping in RevenueCat: configurare gli “Entitlements” che mappano prodotti a permessi.
- Webhook al tuo backend: sincronizzare lo stato dell’abbonamento con il tuo database.
- Paywall: progettare le schermate di acquisto con i componenti di RevenueCat o custom.
Particolarità degli store
Ci sono differenze importanti tra Apple e Google:
- Commissioni: entrambi applicano il 30% il primo anno, il 15% dal secondo (Small Business Program: 15% dall’inizio se fatturi meno di 1M USD/anno).
- Grace period: Apple dà 6-16 giorni di grazia per pagamento fallito. Google dà 3-30 giorni configurabili.
- Cancellazione: su iOS, l’accesso continua fino alla fine del periodo pagato. Su Android, puoi revocare immediatamente o alla fine.
- Prezzo: Apple richiede prezzi dal suo catalogo predefinito. Google consente prezzi liberi.
- Family sharing: Apple supporta la condivisione degli abbonamenti in famiglia. Google anche ma con differenze.
Il caso PEMAV
In PEMAV abbiamo implementato RevenueCat per gestire abbonamenti su iOS e Android con un unico backend. Gli apprendimenti chiave:
- La sincronizzazione tra lo stato dello store e il tuo backend può avere ritardi fino a minuti. Progetta per eventual consistency.
- Gli utenti che cambiano dispositivo (da Android a iOS o viceversa) hanno bisogno di un meccanismo di “restore purchases” robusto.
- Le offerte introduttive (primo mese gratuito, 3 mesi al 50%) sono molto efficaci negli store e RevenueCat le gestisce bene.
Opzione 3: Billing custom su Redsys
Se per requisiti di commissioni o normativi hai bisogno di usare Redsys per gli abbonamenti, devi costruire la logica di billing tu stesso. Redsys fornisce solo la tokenizzazione e l’addebito; il resto è responsabilità tua.
Architettura con Redsys
- Prima transazione: CIT (Cardholder Initiated) con 3D Secure che restituisce un token COF.
- Addebiti ricorrenti: MIT (Merchant Initiated) con il token memorizzato, senza intervento dell’utente.
- Il tuo billing engine: un servizio che esegue addebiti secondo la logica del tuo piano:
- Cron job o scheduler che identifica abbonamenti da rinnovare ogni giorno.
- Logica di retry con backoff esponenziale per pagamenti falliti.
- Calcolo delle prorrazioni quando l’utente cambia piano.
- Generazione di fatture con dati fiscali corretti.
Quando ha senso
Raccomandiamo billing custom su Redsys solo quando:
- Elabori volumi molto alti in Spagna e la differenza di commissioni giustifica lo sviluppo.
- Hai requisiti normativi che richiedono elaborazione bancaria locale.
- Il tuo modello di billing è così specifico che né Stripe Billing né nessuna piattaforma lo supporta nativamente.
In tutti gli altri casi, Stripe Billing fa risparmiare mesi di sviluppo e manutenzione.
Pattern di design per gli abbonamenti
Feature flag per piano
Il pattern che usiamo per controllare l’accesso alle funzionalità:
Piano → [Feature Flag] → Entitlements
Esempio:
- Piano Free: max_projects=3, api_calls=1000/mese, no_export
- Piano Pro: max_projects=unlimited, api_calls=50000/mese, export_csv
- Piano Enterprise: everything + sso + audit_logs + api_unlimited
I feature flag vengono caricati all’inizio della sessione e memorizzati in cache. Quando il piano cambia (via webhook), la cache viene invalidata e gli entitlement vengono ricaricati.
Metering per usage-based billing
Se il tuo pricing ha una componente di utilizzo, hai bisogno di un sistema di metering:
- Registrare l’utilizzo: ogni azione metered (chiamata API, messaggio, GB) viene registrata in un contatore.
- Aggregare per periodo: alla fine del periodo di billing, si calcola il totale.
- Reportare a Stripe: Stripe Usage Records API consente di reportare l’utilizzo che viene fatturato automaticamente.
Il trucco è che il metering deve essere eventual consistent ma non perdere eventi. Usiamo Redis per i contatori in tempo reale e PostgreSQL come source of truth con riconciliazione periodica.
Cancellazione con retention
Il flusso di cancellazione è un’opportunità di retention:
- Sondaggio sui motivi: perché cancella (prezzo, non usa, alternativa, ecc.).
- Offerta contestuale: basata sul motivo:
- Se è il prezzo → offrire sconto o piano inferiore.
- Se è mancanza di utilizzo → offrire pausa temporanea (1-3 mesi).
- Se è un’alternativa → mostrare funzionalità uniche che forse non conosce.
- Conferma: se insiste a cancellare, confermare e chiedere se vuole l’accesso fino alla fine del periodo.
In GolfyApp, questo flusso di retention riduce la cancellazione volontaria del 30%.
Metriche da tracciare
Un sistema di abbonamenti senza analytics è come guidare senza tachimetro. Le metriche minime:
- MRR (Monthly Recurring Revenue): ricavi ricorrenti normalizzati al mese.
- Churn rate: percentuale di abbonati che cancellano per mese (volontario + involontario).
- Trial conversion rate: percentuale di trial che convertono a pagamento.
- Expansion MRR: ricavi aggiuntivi da upgrade e add-on.
- Net Revenue Retention: misura se i clienti esistenti spendono di più o di meno nel tempo (target: >100%).
- LTV: valore totale che genera un cliente durante la sua vita (MRR / churn rate).
- Dunning recovery rate: percentuale di pagamenti falliti che vengono recuperati.
Implementazione passo dopo passo
Settimana 1-2: Fondamenta
- Definire piani e pricing.
- Creare prodotti in Stripe / configurare RevenueCat.
- Implementare checkout / paywall.
- Configurare webhook di base (created, updated, deleted).
- Implementare entitlement system (feature flag per piano).
Settimana 3: Trial e conversione
- Configurare trial (durata, con/senza carta).
- Implementare email automatiche durante il trial.
- Configurare Customer Portal / schermata di gestione abbonamento.
- Implementare flusso di upgrade/downgrade con prorrazioni.
Settimana 4: Dunning e retention
- Configurare Smart Retries in Stripe.
- Implementare email di pagamento fallito con link di aggiornamento.
- Implementare flusso di cancellazione con retention.
- Configurare analytics di abbonamento.
Settimana 5+: Ottimizzazione
- A/B testing di pricing e paywall.
- Ottimizzazione della comunicazione durante il trial.
- Analisi delle coorti e churn per segmento.
- Implementazione del metering se applicabile.
Errori comuni da evitare
- Non gestire il webhook
invoice.payment_failed: senza dunning, perdi il 20-40% dei rinnovi per pagamenti falliti. - Prorrazioni errate: non calcolare correttamente i giorni del periodo corrente genera dispute.
- Race condition nei webhook: Stripe può inviare webhook fuori ordine. Il tuo sistema deve essere idempotente.
- Non memorizzare in cache gli entitlement: consultare il piano ad ogni request è un collo di bottiglia. Metti in cache e invalida via webhook.
- Trial senza attivazione: un trial dove l’utente non sperimenta il valore core ha 0% di conversione.
- Cancellazione immediata senza accesso: se cancelli e interrompi l’accesso immediatamente, l’utente sente di aver perso denaro (ha pagato il periodo ma non può usarlo).
Conclusione
Implementare abbonamenti ricorrenti correttamente richiede di pensare all’intero ciclo di vita: dall’acquisizione (trial) alla retention (dunning, cancellazione con offerte) passando per l’espansione (upgrade, add-on). La tecnologia esiste (Stripe Billing, RevenueCat) per non reinventare la ruota, ma la logica di business che costruisci sopra fa la differenza tra un’azienda che cresce e una che perde clienti per stillicidio.
Se hai bisogno di implementare un sistema di abbonamenti nella tua app o piattaforma, contatta il nostro team. Abbiamo costruito sistemi di billing in produzione con tassi di conversione del 95% e recovery rate del 60%.