Quando il pull non basta: products.json in push + Vercel Blob
L'hosting blocca Vercel con un captcha anti-bot e lo shop si svuota a campione. La fix non è un retry più furbo: è invertire il flusso da pull a push e usare Vercel Blob come unico strato coerente tra container.
Ho un e-commerce B2B su Next.js che legge un products.json da ventisei megabyte servito da un hosting PHP condiviso. Per mesi l'architettura è stata banale: Python esporta il JSON ogni notte via FTP, Vercel lo fetcha a runtime. Poi ho iniziato a vedere lo shop vuoto a campione — pagine prodotto "non trovato", sitemap vuota, intere sessioni senza catalogo.
Tre guasti si erano stratificati in silenzio.
Il primo è l'abitudine di Next.js di cachare anche le risposte sbagliate. Il Data Cache con revalidate: 900 memorizzava per quindici minuti anche le risposte a zero prodotti, così un singolo fetch fallito sporcava la cache per un quarto d'ora buono.
Il secondo è il captcha anti-bot dell'hosting. Sopra una certa soglia di richieste rispondeva con HTML di challenge al posto del JSON — Vercel riceveva text/html, il parsing saltava, e il container serviva un array vuoto.
Il terzo è la natura effimera dei container Vercel. Memoria e /tmp sono per-istanza: ogni nuovo container parte azzerato. Se in quel momento il captcha era attivo, quella sessione vedeva zero prodotti finché l'istanza non moriva.
La soluzione non è stata un retry più lungo o uno user-agent più furbo. Ho invertito il flusso. Invece di Vercel che tenta il pull da un upstream instabile, è il Python dell'export che fa push a un endpoint Next.js con il JSON compresso gzip. L'endpoint valida che l'array prodotti non sia vuoto (safety check contro wipe accidentali) e scrive in tre layer.
Il layer che rende il sistema coerente tra sessioni diverse è Vercel Blob. Memory e /tmp sopravvivono solo finché vive il container; Vercel Blob è storage condiviso — tra container, tra deploy, tra regioni. Un utente su un container appena creato vede lo stesso catalogo di uno su un'istanza calda.
A runtime la lettura è una cascata a cinque livelli: memory cache con TTL un'ora, poi Vercel Blob con timeout a venti secondi per non hangare fino al limite di trecento, poi endpoint PHP dedicato meno esposto al captcha del file statico, poi /tmp senza TTL come safety net (meglio stale che vuoto), infine struttura vuota come disastro totale. Ogni strato tollera il fallimento di quello sotto, e nessuno scrive mai cache vuote.
La morale che mi porto a casa è che quando l'upstream è instabile, aggiungere resilienza al client serve poco. Conviene spostare il lavoro di garanzia sulla parte che puoi controllare: il producer. Il pull è elegante, il push è onesto.