> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Buone pratiche

> Come sviluppare un'app che funzioni e si adatti bene a molti spazi di lavoro.

## Panoramica

L'API di Twenty accetta **500 richieste al minuto per registrazione dell'applicazione** per le richieste effettuate da un'app a proprio nome: esecuzioni senza una persona alle spalle (cron, webhook, hook di installazione) e client creati con `runAs: 'application'`. Il budget è condiviso da ogni spazio di lavoro che ha installato l'app e le richieste che lo superano vengono rifiutate con un `429`. Le richieste effettuate in qualità della persona che ha attivato un'esecuzione vengono invece conteggiate rispetto ai limiti di quella persona. Le pratiche riportate di seguito mantengono un'app entro tale budget man mano che aumenta il numero di installazioni, e entro i limiti dei servizi che chiama.

* **Distribuisci i cron di scansione con un ritardo casuale.** Un trigger cron si avvia in ogni area di lavoro nello stesso minuto, quindi ogni installazione attinge contemporaneamente al budget condiviso. Limita il gestore cron a un accodamento, con un valore `delayMs` casuale su un'ampia finestra temporale, ad esempio un'ora. Gli accodamenti di job sono inoltre limitati a 2.000 al minuto per registrazione dell'applicazione, e un tick cron oltre tale limite viene ignorato nelle aree di lavoro rimanenti; pertanto, mantieni una scansione idempotente e lascia che il tick successivo recuperi.

```ts src/logic-functions/enqueue-nightly-sweep.ts theme={null}
import { defineLogicFunction } from 'twenty-sdk/define';
import { enqueueJobs } from 'twenty-sdk/logic-function';

const NIGHTLY_SWEEP = '3f9d1c02-8a44-4f0e-b1d7-9c2e5a7b4f10';
const SPREAD_WINDOW_MS = 60 * 60 * 1000;

export default defineLogicFunction({
  universalIdentifier: 'b7c2e4d1-0f5a-4c3e-9d8b-6a1f2e3c4d5b',
  name: 'enqueue-nightly-sweep',
  timeoutSeconds: 30,
  cronTriggerSettings: { pattern: '0 3 * * *' },
  handler: async () => {
    await enqueueJobs({
      logicFunctionUniversalIdentifier: NIGHTLY_SWEEP,
      jobs: [{ payload: {} }],
      delayMs: Math.floor(Math.random() * SPREAD_WINDOW_MS),
    });
  },
});
```

```text theme={null}
   pattern "0 3 * * *"                  the server, every minute
                                                  │
              ┌───────────────┬───────────────────┼───────────────┐
              ▼               ▼                   ▼               ▼
        workspace A     workspace B     workspace C   ...   workspace N
          03:00:00        03:00:00        03:00:00            03:00:00
              │               │                   │               │
              └───────────────┴─────────┬─────────┴───────────────┘
                                        ▼
                      500 requests per minute for the whole app
                                   N × calls  →  429
```

Con un ritardo casuale su una finestra di un'ora, le stesse esecuzioni vengono distribuite:

```text theme={null}
   pattern "0 3 * * *"  +  random delayMs in [0, 60 min)
                                                  │
              ┌───────────────┬───────────────────┼───────────────┐
              ▼               ▼                   ▼               ▼
        workspace A     workspace B     workspace C   ...   workspace N
          03:00:00        03:00:00        03:00:00            03:00:00
           + 12 min        + 41 min        + 03 min            + 27 min
              │               │                   │               │
              ▼               ▼                   ▼               ▼
          03:12:00        03:41:00        03:03:00            03:27:00
              │               │                   │               │
              └───────────────┴─────────┬─────────┴───────────────┘
                                        ▼
                      500 requests per minute for the whole app
                          N × calls spread over 60 minutes  →  OK
```

* **Raggruppa in batch gli attivatori di eventi del database.** Una scrittura in blocco, come una sincronizzazione della casella di posta, genera un evento per record, migliaia in pochi secondi, e un'esecuzione per evento significa una richiesta per record. Imposta `batchMode: true`, dichiara `updatedFields` e riduci il batch a record distinti prima di chiamare l'API. Vedi [Raggruppamento in batch degli eventi del database](https://docs.twenty.com/it/developers/extend/apps/logic/logic-functions.md#batching-database-events).

* **Effettua una richiesta per batch, non per record.** Il limite conteggia le richieste, non i record: un `createMany` con `upsert: true` contenente 200 record equivale a una richiesta; 200 aggiornamenti singoli equivalgono a 200 richieste. Leggi con filtri `in` e scrivi con `createMany` o `updateMany`.

* **Comprimi i picchi in un unico job ritardato.** Quando gli eventi rivelano un lavoro più grande dell'evento stesso, accodarlo una volta per evento lo moltiplica per la dimensione del picco. Accoda un job con `delayMs` e un `jobId` deterministico che include una finestra temporale; la coda ignora un ID già presente. Consulta [Scegli il tuo ID job](https://docs.twenty.com/it/developers/extend/apps/logic/background-jobs.md#choose-your-own-job-id).

* **Scagliona i fan-out con `delayMs`.** I job accodati senza ritardo diventano tutti eseguibili contemporaneamente e consumano il budget nello stesso minuto. Raggruppali in slot per minuto e ritarda la pagina successiva in base agli slot utilizzati. Vedi [Job in background](https://docs.twenty.com/it/developers/extend/apps/logic/background-jobs.md).

* **Riprova un `429` con backoff oppure riaccoda con un ritardo.** L'SDK client genera un errore per qualsiasi risposta non 2xx, e un'esecuzione che attende al suo interno consuma il proprio timeout. Riprova con backoff esponenziale e un limite di tentativi, oppure restituisci il lavoro alla coda con un ritardo.

* **Memorizza nella cache ciò che non cambia.** Una ricerca a ogni evento richiede una richiesta per un valore fisso al momento della connessione, ad esempio un'identità o un ID team. Memorizzalo nell'[archivio chiave-valore](https://docs.twenty.com/it/developers/extend/apps/logic/key-value-store.md) quando viene registrata la connessione.

* **Raggruppa in batch le richieste alle API esterne.** Un servizio esterno ha il proprio limite di frequenza e una funzione logica ha un timeout, quindi `n` richieste per esecuzione moltiplicano entrambi. Quando il provider offre un endpoint batch, invia una richiesta per l'intero batch anziché una per record e suddividi il batch in blocchi fino al massimo consentito dal provider.

* **Rendi modificabili dall'utente i parametri predefiniti.** Un valore codificato in una funzione logica o in un Workflows, come una soglia, una dimensione del batch o un'opzione predefinita, è adatto a un'area di lavoro e richiede una nuova release per ogni altra. Dichiaralo come variabile dell'applicazione con un valore predefinito e leggilo al momento dell'esecuzione, affinché gli amministratori dell'area di lavoro possano modificarlo dalle impostazioni dell'app. Vedi [Configurazione dell’applicazione](https://docs.twenty.com/it/developers/extend/apps/config/application.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.