From 7162a27d6deb50f867a16c0e0065cf18cf8c8f5f Mon Sep 17 00:00:00 2001 From: isshaddad Date: Tue, 27 Jan 2026 16:55:05 -0500 Subject: [PATCH 1/2] Runs waiting in queue due to concurrency limits --- docs/troubleshooting.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/troubleshooting.mdx b/docs/troubleshooting.mdx index b6254f62d9..f5a71f02b7 100644 --- a/docs/troubleshooting.mdx +++ b/docs/troubleshooting.mdx @@ -177,6 +177,16 @@ Make sure that you always use `await` when you call `trigger`, `triggerAndWait`, View the [rate limits](/limits) page for more information. +### Runs waiting in queue due to concurrency limits + +If runs are staying in the `QUEUED` state for extended periods, check your concurrency usage in the dashboard. Review how many runs are `EXECUTING` or `DEQUEUED` (these count against limits) and check if any runs are stuck in `EXECUTING` state, as they may be blocking new runs. + +**Solutions:** + +- **Increase concurrency limits** - If you're on a paid plan, increase your environment concurrency limit via the dashboard +- **Review queue concurrency limits** - Check if individual queues have restrictive `concurrencyLimit` settings +- **Check for stuck runs** - See if stalled runs are blocking new executions + ### `Crypto is not defined` This can happen in different situations, for example when using plain strings as idempotency keys. Support for `Crypto` without a special flag was added in Node `v19.0.0`. You will have to upgrade Node - we recommend even-numbered major releases, e.g. `v20` or `v22`. Alternatively, you can switch from plain strings to the `idempotencyKeys.create` SDK function. [Read the guide](/idempotency). From ec6995392370695df2c170ed1ba058350b358c0f Mon Sep 17 00:00:00 2001 From: isshaddad Date: Tue, 27 Jan 2026 17:14:18 -0500 Subject: [PATCH 2/2] Multi-tenant applications --- docs/deploy-environment-variables.mdx | 53 ++++++++++++++++++++++++++- docs/limits.mdx | 8 ++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/docs/deploy-environment-variables.mdx b/docs/deploy-environment-variables.mdx index e123f34170..e7b6496403 100644 --- a/docs/deploy-environment-variables.mdx +++ b/docs/deploy-environment-variables.mdx @@ -360,4 +360,55 @@ This will read your .env.production file using dotenvx and sync the variables to - Trigger.dev does not automatically detect .env.production or dotenvx files - You can paste them manually into the dashboard -- Or sync them automatically using a build extension \ No newline at end of file +- Or sync them automatically using a build extension + +## Multi-tenant applications + +If you're building a multi-tenant application where each tenant needs different environment variables (like tenant-specific API keys or database credentials), you don't need a separate project for each tenant. Instead, use a single project and load tenant-specific secrets at runtime. + + + This is different from [syncing environment variables at deploy time](#sync-env-vars-from-another-service). + Here, secrets are loaded dynamically during task execution, not synced to Trigger.dev's environment variables. + + +### Recommended approach + +Use a secrets service (Infisical, AWS Secrets Manager, HashiCorp Vault, etc.) to store tenant-specific secrets, then retrieve them at the start of each task run based on the tenant identifier in your payload or context. + +**Important:** Never pass secrets in the task payload, as payloads are logged and visible in the dashboard. + +### Example implementation + +```ts +import { task } from "@trigger.dev/sdk"; +import { SecretsManagerClient, GetSecretValueCommand } from "@aws-sdk/client-secrets-manager"; + +export const processTenantData = task({ + id: "process-tenant-data", + run: async (payload: { tenantId: string; data: unknown }) => { + // Retrieve tenant-specific secret at runtime + const client = new SecretsManagerClient({ region: "us-east-1" }); + const response = await client.send( + new GetSecretValueCommand({ + SecretId: `tenants/${payload.tenantId}/supabase-key`, + }) + ); + + const supabaseKey = JSON.parse(response.SecretString!).SUPABASE_SERVICE_KEY; + + // Your task logic using the tenant-specific secret + // ... + }, +}); +``` + +You can use any secrets service - see the [sync env vars section](#sync-env-vars-from-another-service) for an example with Infisical. + +### Benefits + +- **Single codebase** - Deploy once, works for all tenants +- **Secure** - Secrets never appear in payloads or logs +- **Scalable** - No project limit constraints +- **Flexible** - Easy to add new tenants without redeploying + +This approach allows you to support unlimited tenants with a single Trigger.dev project, avoiding the [project limit](/limits#projects) while maintaining security and separation of tenant data. \ No newline at end of file diff --git a/docs/limits.mdx b/docs/limits.mdx index b4df2001ad..45da4e89ab 100644 --- a/docs/limits.mdx +++ b/docs/limits.mdx @@ -55,6 +55,14 @@ If you add them [dynamically using code](/management/schedules/create) make sure If you're creating schedules for your user you will definitely need to request more schedules from us. +## Projects + +| Pricing tier | Limit | +| :----------- | :----------------- | +| All tiers | 10 per organization | + +Each project receives its own concurrency allocation. If you need to support multiple tenants with the same codebase but different environment variables, see the [Multi-tenant applications](/deploy-environment-variables#multi-tenant-applications) section for a recommended workaround. + ## Preview branches | Pricing tier | Limit |