> ## 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.

# Buenas prácticas

> Cómo desarrollar una aplicación que funcione y escale bien en muchos espacios de trabajo.

## Resumen

La API de Twenty acepta **500 solicitudes por minuto por registro de aplicación** para las solicitudes que una aplicación realiza en su propio nombre: ejecuciones sin ninguna persona detrás (cron, webhooks, hooks de instalación) y clientes creados con `runAs: 'application'`. El presupuesto se comparte entre todos los espacios de trabajo que instalaron la aplicación, y las solicitudes que lo superan se rechazan con un `429`. Las solicitudes realizadas como la persona que activó una ejecución cuentan para los límites de esa persona en su lugar. Las prácticas siguientes mantienen una aplicación dentro de ese presupuesto a medida que aumenta su número de instalaciones, y dentro de los límites de los servicios a los que llama.

* **Distribuya las tareas cron de barrido con un retraso aleatorio.** Se inicia un desencadenador cron en cada espacio de trabajo en el mismo minuto, por lo que cada instalación consume el presupuesto compartido a la vez. Limite el controlador cron a una puesta en cola, con un `delayMs` aleatorio en un intervalo amplio, como una hora. Las puestas en cola de trabajos también están limitadas a 2000 por minuto por registro de aplicación, y se omite una activación cron que supere ese límite en los espacios de trabajo restantes, así que mantenga un barrido idempotente y deje que la siguiente activación se ponga al día.

```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 retraso aleatorio en un intervalo de una hora, las mismas ejecuciones se distribuyen:

```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
```

* **Agrupe en lotes los desencadenadores de eventos de base de datos.** Una escritura masiva, como la sincronización de un buzón de correo, emite un evento por registro, miles en cuestión de segundos, y una ejecución por evento implica una solicitud por registro. Establezca `batchMode: true`, declare `updatedFields` y reduzca el lote a registros distintos antes de llamar a la API. Consulte [Agrupación en lotes de eventos de base de datos](https://docs.twenty.com/es/developers/extend/apps/logic/logic-functions.md#batching-database-events).

* **Realice una solicitud por lote, no por registro.** El límite cuenta solicitudes, no registros: un `createMany` con `upsert: true` que contiene 200 registros es una solicitud; 200 actualizaciones individuales son 200. Lea con filtros `in` y escriba con `createMany` o `updateMany`.

* **Consolide los picos en un único trabajo retrasado.** Cuando los eventos revelan trabajo mayor que el propio evento, ponerlo en cola una vez por evento lo multiplica por el tamaño del pico. Ponga en cola un trabajo con `delayMs` y un `jobId` determinista que incluya un intervalo de tiempo; la cola ignora un id que ya contiene. Consulte [Elija su propio id de trabajo](https://docs.twenty.com/es/developers/extend/apps/logic/background-jobs.md#choose-your-own-job-id).

* **Ritme las distribuciones con `delayMs`.** Los trabajos puestos en cola sin retraso pasan a ser aptos todos a la vez y consumen el presupuesto en el mismo minuto. Agrúpelos en intervalos por minuto y retrase la página siguiente según los intervalos utilizados. Consulte [Trabajos en segundo plano](https://docs.twenty.com/es/developers/extend/apps/logic/background-jobs.md).

* **Reintente un `429` con espera progresiva o vuelva a ponerlo en cola con un retraso.** El SDK de cliente genera una excepción ante cualquier respuesta que no sea 2xx, y una ejecución que espera internamente consume su propio tiempo de espera. Reintente con espera progresiva exponencial y un límite de intentos, o devuelva el trabajo a la cola con un retraso.

* **Almacene en caché lo que no cambia.** Una búsqueda en cada evento cuesta una solicitud para un valor fijo en el momento de la conexión, como una identidad o un id de equipo. Almacénelo en el [almacén de clave-valor](https://docs.twenty.com/es/developers/extend/apps/logic/key-value-store.md) cuando se registre la conexión.

* **Agrupe en lotes las solicitudes a API externas.** Un servicio externo tiene su propio límite de tasa y una función de lógica tiene un tiempo de espera, por lo que `n` solicitudes por ejecución multiplican ambos. Cuando el proveedor ofrezca un punto de conexión por lotes, envíe una solicitud para todo el lote en lugar de una por registro y divida el lote según el máximo del proveedor.

* **Haga que el usuario pueda editar los parámetros predeterminados.** Un valor codificado de forma fija en una función de lógica o un Workflow, como un umbral, un tamaño de lote o una opción predeterminada, se ajusta a un espacio de trabajo y obliga a realizar una nueva versión para todos los demás. Declárelo como una variable de aplicación con un valor predeterminado y léalo en tiempo de ejecución, para que los administradores del espacio de trabajo puedan ajustarlo desde la configuración de la aplicación. Consulte [Configuración de la aplicación](https://docs.twenty.com/es/developers/extend/apps/config/application.md).


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