Guide

Come eseguire job in background in un’app web: code, scheduler e cron

Per eseguire job in background in un’app web, dividi innanzitutto il lavoro in due tipi. I job attivati (inviare un’email di benvenuto, elaborare un upload) possono essere salvati in una coda di job, spesso una tabella del database, ed essere gestiti da un worker con tentativi di ripetizione. I job pianificati (un report notturno, promemoria ogni 15 minuti) hanno bisogno di qualcosa che scatti secondo un calendario: la funzione cron dell’host, oppure uno scheduler esterno che richiama un endpoint protetto nella tua app. Fai sempre in modo che i job siano sicuri da eseguire due volte, registra i fallimenti e non affidarti mai a un timer dentro un server che può andare in stop o riavviarsi.

Questa guida spiega le opzioni, quando ognuna è adatta e come configurarle con un creatore di app IA, anche su host che scalano a zero.

Cosa conta come job in background

Qualsiasi lavoro lento, poco affidabile o non necessario per la risposta immediata dell’utente:

  • Invio di email, notifiche e ricevute
  • Ridimensionamento di immagini, transcodifica video, generazione di PDF
  • Chiamate a servizi di terze parti lenti, inclusi modelli IA per attività lunghe
  • Importazione o sincronizzazione di dati da un altro sistema
  • Pulizie notturne, report e promemoria

Farlo dentro la richiesta rende le pagine lente e fragili: se il provider di email è giù, la registrazione dell’utente fallisce. Spostarlo in background significa che l’utente riceve una risposta immediata e il job può essere ritentato.

Le opzioni

OpzioneCome funzionaProContro
Fire-and-forget nello stesso processoRispondi, poi continui il lavoro nel serverNessuna configurazionePersa se il server si ferma; nessun tentativo di ripetizione
Timer nel processo (setInterval, setTimeout)Un timer nel server in esecuzioneBanaleNon gira mentre dorme; duplicati con più copie
Coda su databaseJob salvati come righe; un worker li prende e li esegueUsa il database che hai; durevole; facile da ispezionareDevi costruire tu tentativi e lock; serve qualcosa che esegua il worker
Coda dedicata (basata su Redis o gestita)Un servizio di coda più workerFunzioni mature di tentativi e pianificazioneUn altro servizio da gestire e pagare
Servizio di job o workflow ospitatoUn terzo chiama i tuoi endpoint con tentativi e pianificazioniPianificazione e tentativi gestiti per teDipendenza dal fornitore; un altro account e un’altra chiave
Scheduler esterno che chiama un endpointUn timer altrove invia una richiesta HTTP secondo il calendarioFunziona su qualsiasi host, anche scale-to-zeroIntervalli minimi e ritardi; proteggi l’endpoint
Cron integrato dell’hostLa piattaforma esegue un comando secondo un calendarioSemplice dove c’èNon tutti gli host lo offrono

Non esiste una risposta unica. Una piccola app spesso ha bisogno solo di una coda su database più uno scheduler esterno.

Perché gli host che scalano a zero cambiano il quadro

Molti host moderni mettono in stop la tua app quando nessuno la usa e la riattivano alla richiesta successiva. Questo fa risparmiare denaro, ma un server in stop non esegue codice: i timer non scattano e i worker non controllano la coda. Su questi host, il lavoro pianificato deve partire con una richiesta in arrivo, e la fonte più semplice di quella richiesta è uno scheduler esterno. Ogni chiamata riattiva l’app (e spesso il suo database), quindi chiamare ogni minuto costa più che ogni 15 minuti. Scegli il calendario più lento che soddisfa l’esigenza.

Schema 1: una coda di job su database

Per i job attivati:

  1. Crea una tabella jobs: tipo, payload (JSON), stato (pending, running, done, failed), tentativi, run_after, last_error, timestamp.
  2. Quando succede qualcosa, inserisci una riga di job nella stessa transazione della modifica che l’ha causato, così riescono o falliscono insieme.
  3. Un worker prende i job scaduti, li segna come running, esegue il lavoro e li segna come done.
  4. In caso di fallimento, aumenta attempts, imposta run_after più avanti (per esempio 1, 5, poi 30 minuti) e salva l’errore. Dopo un massimo, segnalo come failed e avvisa qualcuno.

Se più worker potrebbero girare contemporaneamente, i job devono essere presi in modo sicuro. Su Postgres, SELECT ... FOR UPDATE SKIP LOCKED permette a ogni worker di prendere righe diverse senza conflitti.

Chi esegue il worker? Su un server sempre acceso, un ciclo in un processo separato. Su un host che scala a zero, l’endpoint pianificato dello Schema 2 può elaborare un blocco di job scaduti a ogni chiamata.

Schema 2: uno scheduler esterno che richiama la tua app

Per i job pianificati:

  1. Aggiungi un endpoint come POST /api/cron/send-reminders.
  2. Proteggilo: richiedi un token segreto in un header, salvato come segreto da entrambe le parti, e rifiuta qualsiasi altra richiesta.
  3. Rendilo idempotente: eseguirlo due volte nello stesso minuto non deve inviare due promemoria. Registra ciò che è già stato inviato.
  4. Mantieni ogni chiamata breve: elabora un blocco (diciamo 100 elementi) e lascia che la chiamata successiva prenda il resto.
  5. Punta uno scheduler su di esso.

Scelte di scheduler:

  • Workflow pianificati di GitHub Actions. Gratuiti entro i limiti d’uso di GitHub. Secondo la documentazione di GitHub a settembre 2026, l’intervallo minimo è una volta ogni 5 minuti, le esecuzioni possono subire ritardi nelle ore di punta (soprattutto all’inizio di ogni ora), le pianificazioni usano UTC per impostazione predefinita, e i workflow pianificati in un repository pubblico vengono disattivati dopo 60 giorni senza attività nel repository.
  • Servizi cron ospitati. Esistono molti servizi il cui unico compito è chiamare un URL secondo un calendario. Verifica affidabilità, intervallo minimo e avvisi prima di affidarti a uno di essi.
  • Lo scheduler del tuo provider cloud. Se usi già un grande provider cloud, avrà uno scheduler gestito che può chiamare un endpoint HTTPS.
  • Un servizio di job o workflow ospitato. Combinano pianificazione, code e tentativi, e chiamano i tuoi endpoint per ogni passaggio. Confronta prezzi e limiti sul sito di ciascun fornitore.

Schema 3: lascia fare al provider

A volte il miglior job in background è nessun job:

  • Pagamenti. Stripe ripete i pagamenti falliti degli abbonamenti e invia webhook; tu reagisci invece di fare polling. Vedi cos’è un webhook.
  • Email. I provider mettono in coda e ritentano la consegna una volta che hai affidato loro il messaggio.
  • Lavoro IA in blocco. OpenAI e Anthropic offrono API batch per richieste non urgenti che invii e raccogli più tardi.

Prompt da dare al tuo creatore di app IA

Per una coda:

Aggiungi una coda di job in background usando una tabella jobs nel nostro database (tipo, payload JSON, stato, tentativi, run_after, last_error). Quando un utente si registra, inserisci un job send_welcome_email nella stessa transazione invece di inviarla in linea. Aggiungi una funzione processJobs(limit) che prende i job scaduti con SELECT ... FOR UPDATE SKIP LOCKED, li esegue e ritenta i fallimenti dopo 1, 5 e 30 minuti, segnandoli come failed dopo 4 tentativi.

Per un trigger pianificato:

Aggiungi POST /api/cron/tick protetto da un bearer token nel segreto CRON_SECRET; rifiuta qualsiasi richiesta senza di esso. Ogni chiamata esegue processJobs(100) e invia i promemoria di prenotazione scaduti nelle prossime 24 ore che non sono ancora stati inviati, registrando i promemoria inviati così che nulla venga inviato due volte. Restituisci un riepilogo JSON di ciò che è stato eseguito. Poi scrivi un workflow di GitHub Actions che chiama questo endpoint ogni 15 minuti, leggendo URL e token dai segreti del repository.

Errori comuni

  • Affidarsi a setInterval. Si ferma in silenzio quando il server va in stop o si riavvia, e raddoppia quando girano due copie.
  • Un endpoint cron non protetto. Chiunque lo trovi può far scattare i tuoi job, o far salire la tua bolletta email.
  • Job non idempotenti. Tentativi e chiamate duplicate dello scheduler accadranno. Progetta per questo.
  • Nessuna visibilità sui fallimenti. Un job che fallisce in silenzio per una settimana è peggio di uno che fallisce rumorosamente. Registra gli errori e avvisa quando si ripetono.
  • Esecuzioni lunghe in una sola richiesta. Le richieste scadono. Elabora a blocchi.
  • Pianificare troppo spesso. Ogni chiamata su un host che scala a zero riattiva e fattura l’app. Adatta l’intervallo al bisogno reale.
  • Fusi orari. “Le 9” significa cose diverse per lo scheduler (spesso UTC) e per i tuoi utenti. Salva gli orari in UTC e convertili per utente.
  • Segreti nel file del workflow. Tieni i token nello store segreto dello scheduler. Vedi come proteggere le chiavi API.

Checklist

  • Il lavoro lento è stato spostato fuori dalle richieste degli utenti
  • I job sono salvati in modo durevole, non solo in memoria
  • Tentativi con ritardi crescenti e un massimo
  • Ogni job è sicuro da eseguire due volte
  • L’endpoint pianificato è protetto da un token segreto
  • Ogni esecuzione elabora un blocco limitato
  • I job falliti sono visibili, con avvisi
  • L’intervallo di pianificazione è scelto tenendo conto del costo di hosting
  • Gli orari sono salvati in UTC

Job in background su Mythex

La documentazione di Mythex non descrive job pianificati o cron, e le app pubblicate e i loro database vanno in stop quando sono inattivi e si riattivano alla richiesta successiva (vedi Limiti di hosting). Quindi non affidarti a timer dentro la tua app. L’approccio che funziona è quello descritto sopra: chiedi all’agente una tabella di job e un endpoint protetto da token, poi punta uno scheduler esterno sull’URL della tua app pubblicata. Salva il token come segreto del progetto, e ricorda che ogni riattivazione consuma crediti per il tempo in cui l’app e il database sono attivi, quindi scegli un intervallo sensato. Se la tua app ha bisogno di un backend API per questo, la ricetta backend REST API è un punto di partenza, e come costruire una REST API spiega come progettare gli endpoint. Se i worker o i bot sempre attivi sono il cuore del tuo prodotto, un host pensato per processi persistenti potrebbe essere più adatto.

Domande

Cos’è un job in background?

Un job in background è un lavoro che la tua app svolge al di fuori della richiesta per cui l’utente sta aspettando, come inviare email, ridimensionare immagini, generare report o sincronizzare dati. L’utente riceve una risposta rapida, mentre il job viene eseguito a parte e può essere ritentato se fallisce.

Come eseguo un’attività pianificata se il mio host non ha cron?

Aggiungi un endpoint protetto che esegue il lavoro, poi fai in modo che uno scheduler esterno lo richiami secondo un calendario. Le opzioni includono un workflow pianificato di GitHub Actions, un servizio cron ospitato o lo scheduler del tuo provider cloud. Proteggi l’endpoint con un token segreto.

Posso usare setInterval o setTimeout per i job pianificati?

Solo per attività piccole e poco importanti su un server sempre acceso. Se il server si riavvia, scala a zero o gira in più copie, i timer si perdono oppure vengono eseguiti più di una volta. Conserva i lavori pianificati in un database o usa uno scheduler.

Mythex supporta i job cron?

La documentazione di Mythex non descrive job pianificati o cron, e le app pubblicate vanno in stop quando sono inattive. L’approccio affidabile è uno scheduler esterno che richiama un endpoint protetto nella tua app, il quale riattiva l’app ed esegue il lavoro.

Mythex · Pricing · Crea qualsiasi cosa con l'AI · Template per siti web e app · Mythex a confronto · Glossario per creare app con l'AI · Strumenti gratuiti per creare app con l'AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)