Trigger.dev is an open-source background jobs framework providing long-running task execution in distributed systems. The repository is structured as a pnpm monorepo with three package tiers:
Application Layer (apps/*):
apps/webapp: Remix-based control plane exposing REST APIs (/api/v1, /api/v3) and React dashboardapps/coordinator: Socket.IO server for real-time WebSocket communicationapps/supervisor: Container orchestration managing worker lifecycleapps/docker-provider and apps/kubernetes-provider: Runtime environment adaptersInfrastructure Layer (internal-packages/*):
@internal/run-engine: Core execution engine containing RunEngine, DequeueSystem, RunAttemptSystem, and eleven specialized subsystems@trigger.dev/database: Prisma schema and client for PostgreSQL persistence@internal/redis: IORedis wrapper for nine specialized Redis clusters@internal/cache: Tiered caching using @unkey/cachePublic SDK Layer (packages/*):
@trigger.dev/sdk: Developer API exposing task(), schedules.task(), trigger(), and batch operationstrigger.dev: CLI binary providing dev, deploy, init, and management commands@trigger.dev/build: Build extensions (prismaExtension, puppeteerExtension, syncVercelEnvVars)The execution architecture uses PostgreSQL (transactional data), Redis (9 clusters for queuing/locking/caching/pub-sub), ClickHouse (analytics), and S3 (artifacts). Task execution occurs in isolated containers coordinated by the RunEngine state machine.
Sources: package.json1-113 apps/webapp/package.json1-290 packages/trigger-sdk/package.json1-131 packages/cli-v3/package.json1-162 internal-packages/run-engine/src/engine/index.ts1-100
Control Plane (apps/webapp):
entry.server.tsx: Remix SSR entry point with clustering supportserver.ts: Express server mounting Remix request handler on port 3030RunEngine integration via singleton pattern in v3/runEngine.server.tsExecution Engine (internal-packages/run-engine/src/engine/index.ts):
RunEngine class coordinates 11 subsystems: EnqueueSystem, DequeueSystem, RunAttemptSystem, ExecutionSnapshotSystem, CheckpointSystem, WaitpointSystem, BatchSystem, DelayedRunSystem, DebounceSystem, TtlSystem, PendingVersionSystemRunQueue implements hierarchical queue selection (master → environment → task)RunLocker provides distributed locking via Redlock algorithmTaskRunExecutionSnapshot immutable recordsWorker Runtime:
TaskExecutor class (packages/core/src/v3/workers/taskExecutor.ts) executes task run() functionsSupervisorManager (apps/supervisor) using Docker or Kubernetes providersDeveloper Toolchain:
trigger (packages/cli-v3/package.json32-34) implemented using Commander.jstask(), schedules.task(), schemaTask() from packages/trigger-sdk/src/v3/index.tsSources: apps/webapp/entry.server.tsx1-100 apps/webapp/server.ts1-50 internal-packages/run-engine/src/engine/index.ts76-305 packages/core/src/v3/workers/taskExecutor.ts apps/supervisor packages/cli-v3/package.json32-34 packages/trigger-sdk/src/v3/index.ts
Component-to-Code Mapping
The architecture maps to specific code entities:
./dist/esm/index.jstask(), schedules.task(), trigger()RunEngine constructor and 11 subsystemsTaskExecutor.execute() methodSupervisorManager class with createPod() and restoreRun() methodsThe RunEngine subsystems are instantiated in the constructor:
EnqueueSystem (internal-packages/run-engine/src/engine/systems/enqueueSystem.ts)DequeueSystem (internal-packages/run-engine/src/engine/systems/dequeueSystem.ts)RunAttemptSystem (internal-packages/run-engine/src/engine/systems/runAttemptSystem.ts)ExecutionSnapshotSystem, CheckpointSystem, WaitpointSystem, BatchSystem, DelayedRunSystem, DebounceSystem, TtlSystem, PendingVersionSystemSources: apps/webapp/server.ts1-200 packages/cli-v3/package.json32-34 packages/trigger-sdk/src/v3/index.ts internal-packages/run-engine/src/engine/index.ts76-305 packages/core/src/v3/workers/taskExecutor.ts apps/supervisor internal-packages/run-engine/src/engine/systems/dequeueSystem.ts internal-packages/run-engine/src/engine/systems/runAttemptSystem.ts
The codebase is organized as a pnpm workspace monorepo with three distinct package layers:
Package Dependency Graph with Key Classes
The monorepo has three layers:
Sources: package.json1-113 pnpm-lock.yaml38-100 turbo.json1-91
| Package | Location | Purpose |
|---|---|---|
@trigger.dev/core | packages/core | Shared schemas, utilities, and OpenTelemetry integration used across all packages |
@trigger.dev/sdk | packages/trigger-sdk | Public API for defining tasks using task(), scheduled.task(), and triggering runs |
trigger.dev | packages/cli-v3 | Command-line interface providing init, dev, deploy, whoami, and other commands |
@trigger.dev/build | packages/build | Build extensions like prismaExtension(), puppeteerExtension(), syncEnvVars() |
@trigger.dev/database | internal-packages/database | Prisma client and schema for PostgreSQL database access |
@internal/run-engine | internal-packages/run-engine | Core orchestration logic including RunEngine, queue management, and checkpoint systems |
Sources: packages/core/package.json1-50 packages/trigger-sdk/package.json1-50 packages/cli-v3/package.json1-50 packages/build/package.json1-50 internal-packages/database internal-packages/run-engine
The platform relies on multiple specialized data stores and services:
Infrastructure Components and Environment Variables
The system uses nine Redis clusters configured via *_REDIS_HOST environment variables. Each supports optional read replicas (*_REDIS_READER_HOST), TLS configuration (*_REDIS_TLS_DISABLED), and cluster mode (*_REDIS_CLUSTER_MODE_ENABLED). PostgreSQL connections use PrismaClient (internal-packages/database) with pooling controlled by DATABASE_CONNECTION_LIMIT and DATABASE_POOL_TIMEOUT. Container orchestration providers are implemented in apps/docker-provider and apps/kubernetes-provider
Sources: apps/webapp/app/env.server.ts116-260 apps/webapp/app/env.server.ts440-472 docker/Dockerfile1-95 apps/webapp/package.json28-60 internal-packages/database internal-packages/redis
The system uses two database engines:
PostgreSQL (internal-packages/database/prisma/schema.prisma): Stores TaskRun, TaskRunExecution, WorkerDeployment, Organization, Project, RuntimeEnvironment, and other core entities. Connections are managed through PrismaClient and PrismaReplicaClient with connection pooling.
ClickHouse (internal-packages/clickhouse): Stores analytics events, OTEL traces, and usage metrics. Migrations are managed using Goose (docker/scripts/entrypoint.sh13-35).
Sources: apps/webapp/app/env.server.ts52-67 internal-packages/database internal-packages/clickhouse docker/scripts/entrypoint.sh1-48
Nine separate Redis clusters handle different concerns:
| Cluster | Environment Variable | Implementation | Code Location |
|---|---|---|---|
| Rate Limit Redis | RATE_LIMIT_REDIS_* | Ratelimit class from @upstash/ratelimit | apps/webapp/app/env.server.ts127-156 |
| Cache Redis | CACHE_REDIS_* | TriggerCache wrapper over @unkey/cache with RedisCacheStore | internal-packages/cache |
| Realtime Streams Redis | REALTIME_STREAMS_REDIS_* | StreamStore from @s2-dev/streamstore | apps/webapp/app/env.server.ts191-224 |
| PubSub Redis | PUBSUB_REDIS_* | createAdapter() from @socket.io/redis-adapter | apps/webapp/app/env.server.ts231-261 |
| Alert Rate Limiter Redis | ALERT_RATE_LIMITER_REDIS_* | Custom rate limiter for alert emission | apps/webapp/app/env.server.ts440-472 |
| Run Engine Worker Redis | options.worker.redis | Worker class from @trigger.dev/redis-worker | internal-packages/run-engine/src/engine/index.ts187-244 |
| Run Engine Queue Redis | options.queue.redis | RunQueue with FairQueueSelectionStrategy | internal-packages/run-engine/src/engine/index.ts155-185 |
| Run Engine Lock Redis | options.runLock.redis | RunLocker using redlock@5.0.0-beta.2 | internal-packages/run-engine/src/engine/index.ts110-140 |
| Run Engine Presence Redis | Part of queue options | Worker heartbeat tracking | internal-packages/run-engine/src/engine/index.ts155-185 |
Each cluster supports optional read replica configuration with *_READER_HOST and *_READER_PORT variables, TLS configuration via *_TLS_DISABLED, and cluster mode via *_CLUSTER_MODE_ENABLED. The Run Engine clusters use dedicated instances to isolate task execution from web traffic.
Sources: apps/webapp/app/env.server.ts116-260 apps/webapp/app/env.server.ts440-472 internal-packages/redis internal-packages/cache internal-packages/run-engine pnpm-lock.yaml28-37
The typical development and deployment flow:
Developer Workflow Code Flow
Local development:
trigger dev starts DevCommand (packages/cli-v3/src/commands/dev.ts)DevWorker class establishes Socket.IO connection to apps/webappTriggerTaskService to local workerProduction deployment:
DeployCommand (packages/cli-v3/src/commands/deploy.ts) invokes InitializeDeploymentServicebuildImage() function with Depot or local DockerFinalizeDeploymentService promotes deployment and updates WorkerDeployment statusRunEngine.enqueue() adds runs to Redis queue with QUEUED statusDequeueSystem.dequeue() assigns runs to workersTaskExecutor.execute() runs the task code and reports completionSources: packages/cli-v3/src/commands/dev.ts packages/cli-v3/src/commands/deploy.ts apps/webapp/app/runEngine/services/triggerTask.server.ts internal-packages/run-engine/src/engine/systems/dequeueSystem.ts packages/core/src/v3/workers/taskExecutor.ts
The deployment process transforms developer code into containerized workers:
Build and Deployment Pipeline
The CLI supports three build modes via command-line flags. Build extensions (packages/build/src/extensions) modify Docker images to include dependencies. The WorkerDeployment table tracks deployment state transitions.
Sources: packages/cli-v3/package.json83-148 packages/build/package.json1-50 apps/webapp/app/env.server.ts288-331 docker/Dockerfile1-95
Build extensions enable customization of the worker container image:
prismaExtension(): Generates Prisma client with three modes (legacy, engine-only, modern)puppeteerExtension(): Installs Chromium and Puppeteer dependenciesplaywrightExtension(): Installs Playwright browserssyncEnvVars(): Syncs environment variables to Trigger.dev platformaptGet(), ffmpegExtension(): Install system packagesExtensions are defined in trigger.config.ts and processed during the build phase.
Sources: packages/build/package.json1-216 packages/build/CHANGELOG.md1-350
The platform integrates OpenTelemetry for comprehensive observability:
Observability Architecture
OpenTelemetry instrumentation exports traces, logs, and metrics to configurable endpoints. The internal-packages/tracing package provides structured logging utilities.
Sources: apps/webapp/package.json65-83 apps/webapp/app/env.server.ts405-421 internal-packages/tracing packages/core/package.json168-183
The platform provides real-time updates through multiple channels:
Server-Sent Events (SSE): The RunStreamPresenter class streams run execution events to clients. React hooks like useRealtimeRun() consume these streams.
Socket.IO: The apps/coordinator application provides WebSocket-based bidirectional communication using Socket.IO with Redis adapter for horizontal scaling.
Electric SQL: The @electric-sql/react package provides real-time database synchronization for PostgreSQL data, enabling live updates of run status without polling.
Sources: apps/webapp/package.json52-54 apps/coordinator packages/react-hooks/package.json1-76
System configuration is managed through multiple mechanisms:
Environment Variables: The apps/webapp/app/env.server.ts1-600 file defines a comprehensive Zod schema validating 200+ environment variables controlling database connections, Redis clusters, deployment registries, OTEL configuration, and feature flags.
Trigger Config: Developers define trigger.config.ts files specifying build extensions, runtime configuration, and telemetry settings using defineConfig() from @trigger.dev/sdk/v3.
Deployment Configuration: Registry configuration, image tags, and platform settings are managed through environment variables with prefixes like DEPLOY_REGISTRY_* and V4_DEPLOY_REGISTRY_*.
Sources: apps/webapp/app/env.server.ts1-600 packages/trigger-sdk/CHANGELOG.md1-350
Refresh this wiki
This wiki was recently refreshed. Please wait 7 days to refresh again.