DIEGO CECATO / NOTE DAL CAMPO

Il cloud non rompe il codice: rompe gli assunti che non avevi scritto

diego cecato//
Cover editoriale: Il cloud non rompe il codice, rompe gli assunti che non avevi scritto

Quando una migrazione verso un PaaS managed va storta, la spiegazione più comoda è quasi sempre la stessa: «il cloud è diverso». È vera, ma serve a poco. La domanda utile è un’altra: quali assunti della nostra applicazione erano rimasti impliciti finché avevamo un server sotto mano?

Il nuovo playbook pubblicato da Laravel per migrare da Forge a Laravel Cloud è interessante proprio perché, sotto una procedura apparentemente ordinaria, mette in fila questi assunti. Database, filesystem, processi in background, configurazione Nginx, DNS, variabili d’ambiente e rollback: non sono dettagli collaterali al deploy. Sono parte del sistema, anche quando il codice applicativo fa finta che non esistano.

Laravel usa Pinkary come caso operativo e sostiene che, per molte applicazioni, il codice cambi poco o nulla. È plausibile perché Forge e Cloud restano nello stesso ecosistema. Ma il punto più utile non è la promessa commerciale di una migrazione facile. È ciò che bisogna rendere esplicito prima di poterla chiamare facile.

Il server perdona molti assunti impliciti

Forge automatizza parecchio lavoro, ma alla fine stai ancora amministrando una macchina: hai accesso SSH, un filesystem persistente, Nginx, processi, database e servizi che puoi configurare direttamente. Questa libertà è utile, ma crea anche una zona grigia in cui molte decisioni architetturali diventano abitudini operative.

Un upload finisce sul disco locale perché «tanto è lì». Un redirect vive in una regola Nginx aggiunta mesi fa. Un worker gira come processo perché qualcuno lo ha configurato una volta. Una variabile è presente in produzione ma nessuno ricorda più dove sia documentata. Il database e la cache condividono magari la stessa macchina perché, fino a quel momento, andava bene così.

Finché controlli il server, puoi compensare queste dipendenze con interventi manuali. Quando passi a una piattaforma managed, quella possibilità si riduce deliberatamente. E improvvisamente ciò che sembrava «infrastruttura» torna a essere ciò che è sempre stato: una dipendenza dell’applicazione.

Una migrazione managed non crea necessariamente nuovi problemi. Spesso toglie semplicemente il posto in cui avevamo nascosto quelli vecchi.

Il filesystem locale è il primo test di realtà

Il playbook Laravel è molto esplicito su un caso classico: se l’applicazione salva file sul disco del server Forge, quei file devono essere spostati su object storage S3-compatible e la configurazione del filesystem va aggiornata. Se l’applicazione usava già S3, invece, il passaggio è principalmente di configurazione.

La differenza sembra banale, ma misura bene quanto l’applicazione sia davvero separata dall’ambiente che la ospita. Scrivere su storage/app non è sbagliato in assoluto. Diventa un vincolo quando la persistenza di quel percorso viene data per scontata e nessuno l’ha trattata come una scelta architetturale.

Su una piattaforma che può creare, sostituire o scalare repliche, il concetto di «quel server» perde importanza. Il dato persistente deve vivere in una risorsa pensata per esserlo. È la stessa lezione che ritorna in molti sistemi moderni: più rendiamo effimero il compute, più dobbiamo essere precisi su dove risiede lo stato.

Queue e processi: il problema non è avviarli, è dichiararli

Su Forge possiamo configurare processi background e tenerli in esecuzione sul server. Laravel Cloud li tratta come managed queue workers che possono scalare con il carico. Anche qui il vantaggio operativo è evidente, ma la migrazione obbliga a formalizzare una domanda spesso trascurata: quali processi fanno davvero parte dell’applicazione?

Se per capire come gira un progetto dobbiamo entrare nel server e guardare cosa è stato configurato nel tempo, abbiamo già perso una parte della descrizione del sistema. Il deploy del repository non racconta tutto. Esiste una seconda architettura, fatta di process manager, cron, regole del web server, storage e servizi esterni.

Un PaaS riduce il numero di manopole, ma in cambio pretende che queste esigenze siano espresse attraverso primitive riconoscibili: web compute, queue worker, scheduler, database, cache, object storage. È meno libertà locale e più contratto esplicito.

Anche Nginx è codice, solo che spesso ce ne dimentichiamo

La guida ufficiale avverte di controllare eventuali regole Nginx personalizzate — redirect, header, rate limit e altre personalizzazioni — perché Laravel Cloud gestisce il web server. È uno dei passaggi più importanti dell’intero playbook.

Una configurazione modificata direttamente sul server può diventare parte del comportamento pubblico dell’applicazione senza comparire nel repository. Se sparisce durante la migrazione, dal punto di vista dell’utente il software è cambiato anche se non abbiamo toccato una riga PHP.

Questo è il genere di dipendenza che tende a emergere tardi, perché non fallisce necessariamente il deploy. L’applicazione parte, la home risponde, i test superficiali sono verdi. Poi scopri che un redirect storico non esiste più, che un header aveva una funzione precisa o che una regola di rate limiting era diventata una parte non documentata del perimetro operativo.

È anche il motivo per cui considero pericoloso ridurre l’architettura al codice applicativo. In un altro contesto ho scritto di come una proprietà apparentemente contenuta in un layer possa in realtà dipendere da ciò che accade sotto. Qui il problema è meno spettacolare, ma la logica è la stessa: il comportamento reale nasce dall’insieme dei layer, non da quello che preferiamo guardare.

Il database è una migrazione, non un allegato al deploy

Il playbook separa correttamente provisioning, export e import del database dal deploy dell’applicazione. Per MySQL propone mysqldump; per PostgreSQL pg_dump e pg_restore. La piattaforma può automatizzare la creazione della risorsa, ma non può inventarsi la strategia con cui trasferiamo lo stato di produzione.

Qui emerge una distinzione che vale ben oltre Laravel: automatizzare il provisioning non automatizza automaticamente la migrazione dei dati. Dimensione del database, tempo di dump e restore, scritture durante il cutover, compatibilità, privilegi e finestra di manutenzione restano problemi da progettare.

La stessa documentazione Laravel mostra scenari molto diversi: una normale applicazione può spostarsi rapidamente, mentre un caso pubblicato da Laravel su PyleSoft racconta la migrazione di circa 300 GB di dati e la necessità di dry run, snapshot e strumenti specifici come mydumper/myloader. La piattaforma è la stessa; il rischio operativo no.

Il passaggio più importante è quello che permette di tornare indietro

La parte migliore della guida è probabilmente il rollback plan: tenere Forge attivo finché Cloud non è stato validato, provare l’applicazione sulla preview URL e conservare i vecchi record DNS per poter tornare rapidamente alla configurazione precedente.

È un approccio molto meno eroico del classico «migration day», ed è proprio per questo che funziona meglio. Una migrazione non dovrebbe dimostrare che siamo abbastanza bravi da non sbagliare. Dovrebbe essere progettata assumendo che qualcosa possa sfuggire ai test.

Abbassare il TTL DNS prima del cutover, predisporre l’infrastruttura prima di fare deploy, testare sull’URL temporaneo, verificare code e funzionalità critiche, mantenere temporaneamente entrambe le piattaforme: sono tutte scelte che riducono il costo dell’errore invece di fingere di poterlo eliminare.

Un deploy riuscito dimostra che il nuovo ambiente parte. Un rollback progettato dimostra che abbiamo capito il rischio.

Managed non significa senza infrastruttura

È facile raccontare il passaggio da Forge a Cloud come eliminazione dell’infrastruttura. Tecnicamente non succede nulla del genere. L’infrastruttura continua a esistere; cambia chi la gestisce e, soprattutto, cambia l’interfaccia attraverso cui l’applicazione la usa.

Su Forge puoi avere root access e intervenire direttamente sulla macchina. Su Cloud lavori con risorse gestite, autoscaling, scale-to-zero, queue worker, database, cache e object storage. Guadagni standardizzazione e riduci una parte del lavoro operativo, ma rinunci volontariamente a una parte della libertà del server.

Non è automaticamente un vantaggio per ogni progetto. Se hai dipendenze di sistema particolari, networking personalizzato o configurazioni che richiedono controllo diretto della macchina, Forge continua ad avere un senso preciso. La stessa comparazione ufficiale di Laravel presenta Forge come scelta adatta quando servono root access, pacchetti specifici o configurazioni di rete personalizzate.

La decisione quindi non dovrebbe essere «server vecchio, PaaS moderno». Dovrebbe essere: quanta infrastruttura vogliamo possedere e quanta vogliamo trasformare in un contratto con la piattaforma?

La vera preparazione avviene prima della migrazione

Se dovessi estrarre un metodo generale da questo caso, non partirei dal pulsante “New application”. Partirei da un inventario delle dipendenze che oggi vivono fuori dal codice.

  • Dove vive lo stato persistente?
  • Quali processi devono rimanere attivi e con quali regole di scaling?
  • Quali configurazioni del web server cambiano il comportamento dell’applicazione?
  • Quali variabili e secret sono necessari?
  • Come vengono eseguiti scheduler e job?
  • Quanto tempo richiede realmente spostare database e file?
  • Come verifichiamo il nuovo ambiente prima del traffico reale?
  • Qual è il percorso di ritorno se una dipendenza dimenticata emerge dopo il cutover?

Se sappiamo rispondere a queste domande, la scelta tra Forge, Laravel Cloud o un’altra piattaforma diventa molto più razionale. Se non sappiamo rispondere, il problema non è ancora il provider: è che non possediamo una descrizione sufficientemente completa del sistema che stiamo cercando di spostare.

Ed è qui che il playbook di Laravel diventa più utile del prodotto che sta promuovendo. Una buona migrazione non consiste nel trasferire un repository da un pannello all’altro. Consiste nel trasformare assunti accumulati negli anni in dipendenze esplicite, verificabili e possibilmente reversibili.

Il cloud managed non elimina la complessità. Decide dove deve stare. Se quella decisione ci costringe finalmente a documentare filesystem, processi, stato, rete e rollback, forse il beneficio più importante della migrazione arriva ancora prima di spostare il primo byte.

Domande frequenti

Qual è la differenza principale tra Laravel Forge e Laravel Cloud?

Forge gestisce e configura server che restano sotto il tuo controllo, con accesso alla macchina e maggiore libertà operativa. Laravel Cloud espone invece compute, database, cache, queue e storage come risorse gestite, riducendo la gestione diretta dell’infrastruttura.

Perché il filesystem locale può creare problemi durante una migrazione verso un PaaS?

Perché le repliche di compute possono essere effimere o sostituite. I file che devono sopravvivere al ciclo di vita della singola istanza vanno spostati su storage persistente, per esempio object storage S3-compatible.

Come si riduce il rischio durante il cutover da Forge a Laravel Cloud?

Il playbook Laravel suggerisce di predisporre e testare Cloud prima dello switch, abbassare in anticipo il TTL DNS, mantenere Forge attivo finché il nuovo ambiente non è validato e conservare i vecchi record DNS per un rollback rapido.

Una migrazione a Laravel Cloud richiede sempre modifiche al codice?

Non necessariamente. Per molte applicazioni Laravel le modifiche possono essere limitate, ma dipendenze da filesystem locale, configurazioni Nginx personalizzate, processi background e altre assunzioni legate al server devono essere identificate e adattate.