Cloud Code è un modello serverless in cui la logica del backend gira come funzioni lato server, attivate da chiamate, eventi sui dati o pianificazioni. Due chiarimenti subito, perché questa famiglia di termini vive nella confusione. Primo: “serverless” significa che i server sono un problema di qualcun altro – esistono, invisibili, e li scala qualcun altro. Secondo: le funzioni esistono in due architetture, il FaaS autonomo, dove ogni funzione è un’unità isolata cablata a servizi esterni, e la variante BaaS che dà il nome a questo articolo, cioè funzioni distribuite dentro il backend, che condividono l’ambiente con il database, l’autenticazione e i file su cui agiscono.
Punti chiave
| Domanda | Risposta |
|---|---|
| Le quattro proprietà | Attivate da eventi · stateless · scalabilità automatica · pagamento a consumo |
| Le due varianti | Unità FaaS autonome vs. Cloud Code che vive insieme al backend |
| Le famiglie di trigger | Chiamata per nome · eventi sui dati · eventi di autenticazione · pianificazioni · webhook |
| Perché lato server | I client si possono decompilare; le funzioni non si possono manomettere |
| I limiti onesti | Timeout, statelessness e cold start (dove vale la scalabilità fino a zero) |
Una funzione, chiamata da ovunque
L’esempio classico dell’aggregazione – calcolare accanto ai dati e spedire solo la risposta:
// JavaScript / Node.js — Back4app JS SDK
// Calling a Cloud Code function: server-side logic, one line from the client
const avg = await Parse.Cloud.run('averageStars', { movie: 'Arrival' });
// The aggregation ran NEXT TO the database — only the answer crossed the wire
// The function itself (cloud/main.js — deployed to your backend, not the app):
// Parse.Cloud.define('averageStars', async (req) => {
// const q = new Parse.Query('Review').equalTo('movie', req.params.movie);
// const reviews = await q.find({ useMasterKey: true });
// return reviews.reduce((s, r) => s + r.get('stars'), 0) / reviews.length;
// }); // Flutter / Dart — Back4app Flutter SDK
// Calling a Cloud Code function: server-side logic, one line from the client
final response = await ParseCloudFunction('averageStars')
.execute(parameters: {'movie': 'Arrival'});
final avg = response.result;
// The aggregation ran NEXT TO the database — only the answer crossed the wire
// The function lives in cloud/main.js on your backend — update it anytime;
// every client gets the new logic instantly, no app-store release required. // iOS / Swift — Back4app Swift SDK
// Calling a Cloud Code function: server-side logic, one line from the client
let avg: Double = try await Cloud.run(name: "averageStars",
parameters: ["movie": "Arrival"])
// The aggregation ran NEXT TO the database — only the answer crossed the wire
// The function lives in cloud/main.js on your backend — update it anytime;
// every client gets the new logic instantly, no app-store release required. // Android / Kotlin — Back4app Android SDK
// Calling a Cloud Code function: server-side logic, one line from the client
val params = mapOf("movie" to "Arrival")
val avg = ParseCloud.callFunction<Double>("averageStars", params)
// The aggregation ran NEXT TO the database — only the answer crossed the wire
// The function lives in cloud/main.js on your backend — update it anytime;
// every client gets the new logic instantly, no app-store release required. Calcolare la media di mille recensioni sul telefono significa scaricare mille recensioni; la versione con la funzione sposta un numero solo. Quell’argomento sulla banda si generalizza fino a diventare l’intera tesi a favore della logica lato server, qui sotto.
La tassonomia dei trigger
Le spiegazioni superficiali liquidano i trigger in una frase; la struttura merita una tabella:
| Famiglia di trigger | Si attiva quando | Uso canonico |
|---|---|---|
| Funzioni chiamabili | Un client invoca per nome con parametri JSON | Logica di business, aggregazioni, azioni |
| Trigger sui dati | Prima/dopo save, delete, find su una classe | Validazione, valori predefiniti, cascate, audit |
| Trigger di autenticazione | Prima del login, dopo registrazione/logout | Blocklist, flussi di benvenuto, eventi di audit |
| Job pianificati | Espressioni cron | Report, pulizie, purghe TTL, digest |
| Webhook in ingresso | Un sistema esterno invia un evento in POST | Conferme di pagamento, notifiche CI |
Perché la logica sta lato server
Quattro argomenti, quasi sempre assenti dalle spiegazioni abituali. Non fidarsi del client: le app si decompilano e le richieste si falsificano; calcoli di prezzo, controlli sui permessi e punteggi di gioco calcolati sul dispositivo sono suggerimenti, mentre la stessa logica dentro una funzione è legge – un trigger beforeSave valida ogni scrittura, qualunque client l’abbia inviata. I segreti restano a casa: le chiavi API di terze parti vivono nell’ambiente della funzione, mai in un bundle che chiunque può aprire – la disciplina delle chiavi API resa strutturale. Aggiornare senza release: le modifiche alla logica di server raggiungono ogni utente all’istante, senza un ciclo di revisione dell’app store tra la correzione e il corretto. Calcolare vicino ai dati: aggregazioni, modellazione delle ricerche e fan-out girano a microsecondi dal database invece che dall’altro capo di una rete mobile.
Cloud Code vs. FaaS autonomo vs. container
| Cloud Code (funzioni BaaS) | FaaS autonomo | Container | |
|---|---|---|---|
| Dove gira | Dentro il runtime del backend | Unità isolate per funzione | Dove vengono orchestrati |
| Contesto | Database, autenticazione e ACL già collegati | Ogni servizio cablato a mano | Quello che ci si costruisce dentro |
| Unità di deployment | Un codebase, un deployment | Per funzione | Per immagine |
| Cold start | Nessuno: il backend è già attivo | Sì, alla ripartenza da zero | Solo se si scende a zero |
| Operazioni privilegiate | Accesso con master key per la logica di amministrazione | Cablaggio IAM per funzione | Il proprio tessuto di autenticazione |
| Scalabilità | Insieme al backend | Per richiesta, fino a zero | Secondo configurazione |
| Adatto a | Backend di app su un BaaS | Lavoro a eventi isolato e a picchi | Servizi di lunga durata e con stato |
La voce architettura serverless copre il modello nel suo insieme e il posto del FaaS nella scala dei servizi ha un articolo dedicato; la riga che conta qui è contesto: le funzioni Cloud Code nascono connesse – stesso SDK, stessa semantica di sessione, ACL applicate alle loro query – là dove il FaaS autonomo comincia ogni progetto dall’idraulica.
Cold start e statelessness, senza giri di parole
Dalla scalabilità per singola richiesta discendono due proprietà, ed entrambe vanno dette senza ambiguità. I cold start capitano quando una funzione scesa a zero deve inizializzare un ambiente prima di girare: da qualche centinaio di millisecondi a qualche secondo sulle piattaforme tipiche, attenuati da istanze calde minime e bundle leggeri, e architetturalmente assenti per le funzioni ospitate su un backend sempre attivo, il che è una differenza reale tra le due varianti, non una vanteria commerciale. La statelessness significa che, per contratto, nulla in memoria sopravvive tra un’invocazione e l’altra: contatori, cache e sessioni tenuti dentro una funzione sono bug a orologeria. Lo stato va nel database – e il vantaggio silenzioso della variante BaaS è che il database dista una riga di codice, invece di essere un servizio da scegliere, collegare e mettere in sicurezza prima.
Casi d’uso tipici
- Validazione e regole di business – barriere
beforeSaveche rendono gli invarianti non negoziabili su ogni client. - Aggregazioni e report – calcolare accanto ai dati; restituire risposte, non dataset.
- Integrazioni con terze parti – pagamenti, e-mail, API di IA chiamate con segreti custoditi lato server.
- Ricevitori ed emettitori di webhook – le funzioni come volto HTTP delle integrazioni a eventi.
- Manutenzione pianificata – digest, pulizie e purghe su cron, senza una flotta di worker da gestire.
Farne una funzione? Matrice decisionale
| Lavoro | Destinazione |
|---|---|
| Logica che i client potrebbero manomettere | Funzione – sempre |
| Compiti a picchi, di forma event-driven | Funzione |
| Calcolo di lunga durata (minuti o più) | Job in background, non una funzione |
| Servizi con stato, sempre attivi (socket, code) | Container / servizi di piattaforma |
| Hot path critico in latenza a volume enorme e costante | Misurare – il sempre acceso può vincere |
| Tutto ciò che tocca un segreto | Funzione – il segreto non viene mai distribuito |
Limiti e trade-off
- I timeout sono contratti. Le funzioni hanno un tetto da qualche secondo a qualche minuto; il lavoro che rischia di sforarlo pretende una coda di job, non speranza.
- La statelessness è severa. Tutto ciò che sta in memoria è effimero; i progetti che lo dimenticano passano i test e crollano sotto scale-out.
- La proliferazione è la modalità di guasto. Cinquanta funzioni piccole senza moduli condivisi né disciplina di denominazione diventano un monolite distribuito con strumenti peggiori.
- Il debug è remoto per natura. Log e tracce sostituiscono i breakpoint; qui le piattaforme con buone superfici di log si guadagnano lo stipendio.
- Il costo si inverte sotto carico costante. Il pagamento a consumo è imbattibile sul lavoro a picchi e battibile dai server sempre accesi a throughput elevato e costante: conviene calcolare la curva, non leggere la brochure.
Cloud Code 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. Qui Cloud Code è la variante BaaS nella sua forma originale: JavaScript distribuito dentro il backend Back4app – Parse.Cloud.define per le funzioni chiamabili come quella delle schede di codice, trigger beforeSave/afterSave per le regole sui dati, hook di autenticazione e job pianificati, tutto in un codebase e un deployment. Le funzioni girano con il contesto già collegato: lo stesso SDK usato dai client, ACL e permessi a livello di classe applicati alle query, accesso con master key disponibile quando la logica di amministrazione ha legittimo bisogno di aggirarli, e i segreti nella configurazione lato server. Poiché il backend è sempre attivo, il cold start della ripartenza da zero semplicemente non si applica – e poiché la piattaforma è open source, le funzioni sono portabili su qualsiasi host che la esegua, che è la risposta pratica alla questione del lock-in.
Domande frequenti
Che cos'è una funzione serverless?
Un piccolo blocco di codice lato server, dedicato a un solo compito, che la piattaforma esegue su richiesta in risposta a un evento: una chiamata HTTP, una modifica dei dati, una pianificazione. Il provider si occupa di provisioning, scalabilità e manutenzione. Si distribuisce la logica; la piattaforma possiede il macchinario che la esegue.
Qual è la differenza tra FaaS e serverless?
FaaS – Functions-as-a-Service – è la metà di calcolo del serverless: singole funzioni attivate da eventi. Serverless è il modello più ampio, che comprende anche i servizi di backend gestiti (database, autenticazione, archiviazione: la metà BaaS). Cloud Code è il punto in cui le due metà si incontrano, cioè funzioni che girano insieme a un backend gestito.
Come vengono attivate le funzioni serverless?
Cinque famiglie: le chiamate dirette (un client o un'API invoca la funzione per nome), gli eventi sui dati (codice che gira prima o dopo salvataggi ed eliminazioni), gli eventi di autenticazione (hook su login e registrazione), le pianificazioni (job in stile cron) e i webhook in ingresso da sistemi esterni. Una buona piattaforma espone tutte e cinque come semplice registrazione di codice, non come infrastruttura.
Che cos'è un cold start?
La latenza – da qualche centinaio di millisecondi a qualche secondo – che si paga quando la piattaforma deve inizializzare un ambiente di esecuzione nuovo per una funzione scesa a zero istanze. Tra le mitigazioni ci sono le istanze calde minime e i bundle più leggeri; le funzioni ospitate su un backend sempre attivo evitano del tutto il caso della ripartenza da zero.
Perché le funzioni serverless devono essere stateless?
Perché la richiesta successiva può essere servita da una qualsiasi delle molte istanze parallele ed effimere: la memoria conservata tra un'invocazione e l'altra è un bug a orologeria. Lo stato persistente sta in un database o in una cache. Nella variante BaaS il database è già collegato, ed è buona parte della comodità del modello.
Quali sono i limiti delle funzioni serverless?
Le piattaforme impongono un tetto al tempo di esecuzione (qualche secondo per impostazione predefinita, qualche minuto al massimo), alla memoria e alla dimensione dei payload. Il lavoro di lunga durata appartiene ai job in background, e un throughput elevato e costante può costare più di un server sempre acceso. I limiti sono il prezzo della scalabilità per singola richiesta.
Qual è la differenza tra funzioni serverless e microservizi?
Assi diversi: i microservizi sono una scomposizione architetturale, serverless è un modello di esecuzione. Una funzione è più granulare di un microservizio, e un microservizio può essere realizzato come funzioni, container o fetta di monolite. I container comprano controllo e processi di lunga durata; le funzioni comprano zero operatività e scalabilità per singola richiesta.
Le funzioni serverless causano vendor lock-in?
I formati di evento e gli strumenti proprietari creano un accoppiamento reale sulle piattaforme chiuse. Il contrappeso è l'open source: le funzioni scritte su runtime aperti – incluso il Cloud Code open-source di Back4app, che gira su qualsiasi host Node.js – si spostano insieme al backend invece di vincolare a un solo sistema di eventi.