Thanks to visit codestin.com
Credit goes to deepwiki.com

Menu

Development and Deployment

Relevant source files

This document covers the complete development lifecycle from local development to production deployment. It explains the trigger dev command for rapid iteration, the trigger deploy command for building and deploying worker containers, the multi-stage Docker build pipeline, environment configuration management, and CI/CD integration patterns.

For information about the runtime execution environment and task orchestration after deployment, see Task Execution Engine. For details about the webapp server infrastructure, see Web Application.

Overview

The Trigger.dev platform supports two distinct operational modes with different build and execution flows:

Sources: packages/cli-v3/src/commands/deploy.ts155-590 apps/webapp/app/v3/marqs/devQueueConsumer.server.ts1-500 apps/webapp/app/v3/services/createBackgroundWorker.server.ts1-286

Local Development

The trigger dev command provides a hot-reloading development environment where tasks execute in a local Node.js process rather than containers. This enables rapid iteration without Docker builds.

Development Command Flow

The development flow involves several key services and data structures:

ComponentClass/FunctionPurpose
CLI CommandNot provided in filesParses args, authenticates, starts build
Config LoadingloadConfig()Resolves trigger.config.ts and workspace
Worker BuildbuildWorker()Bundles code with esbuild, no Docker
Session ManagementcreateNewSession(), disconnectSession()Tracks active dev connections
Dev Queue ConsumerDevQueueConsumerProcesses messages from Marqs queue
Worker RegistrationregisterBackgroundWorker()Links worker ID to queue consumer

Sources: apps/webapp/app/v3/marqs/devQueueConsumer.server.ts42-500 apps/webapp/app/models/runtimeEnvironment.server.ts14

DevQueueConsumer Architecture

The apps/webapp/app/v3/marqs/devQueueConsumer.server.ts42-500 implements message processing for development workers:

Key characteristics of development mode:

  • No containerization: Tasks execute in the local Node process
  • Hot reloading: File changes trigger rebuild without reconnection
  • Single session: Each trigger dev creates one RuntimeEnvironmentSession
  • Pub/Sub updates: Uses Redis pub/sub for task completion notifications
  • Manual queueing: Developer triggers tasks via dashboard or SDK

Sources: apps/webapp/app/v3/marqs/devQueueConsumer.server.ts42-500 apps/webapp/app/v3/marqs/devPubSub.server.ts1-50

Deployment Process

The trigger deploy command builds a Docker image containing the worker code and pushes it to a container registry. The deployment then goes through an indexing phase to discover tasks before becoming active.

Deployment Command Structure

The deployCommand() function in packages/cli-v3/src/commands/deploy.ts159-163 orchestrates a multi-phase process:

Sources: packages/cli-v3/src/commands/deploy.ts159-590 apps/webapp/app/v3/services/initializeDeployment.server.ts18-120 apps/webapp/app/v3/services/finalizeDeploymentV2.server.ts11-164

Deployment Configuration

The DeployCommandOptions schema in packages/cli-v3/src/commands/deploy.ts46-64 defines deployment parameters:

OptionTypeDefaultPurpose
env"prod" | "staging" | "preview" | "production""prod"Target environment (production coerced to prod)
branchstring?Auto-detectPreview branch name
configstring?undefinedConfig file name override
projectRefstring?undefinedProject ref override
dryRunbooleanfalseSkip actual deployment
skipSyncEnvVarsbooleanfalseSkip env var sync
skipPromotionbooleanfalseDon't promote to current
skipUpdateCheckbooleanfalseSkip package version check
noCachebooleanfalseDisable Docker cache
saveLogsbooleanfalseSave logs even on success
envFilestring?undefinedPath to .env file
loadboolean?undefinedLoad image into local Docker
pushboolean?undefinedPush after local build
forceLocalBuildboolean?undefinedForce local build instead of remote
network"default" | "none" | "host"?undefinedDocker build networking
builderstring"trigger"Docker buildx builder

Sources: packages/cli-v3/src/commands/deploy.ts46-64

Build Worker Process

The buildWorker() function (referenced but not provided in files) uses esbuild to bundle task code with the following characteristics:

The build produces a BuildManifest containing:

  • contentHash: SHA-256 of bundled code for deduplication
  • runtime: Node.js or other runtime identifier
  • deploy.sync.env: Environment variables to sync with server
  • deploy.sync.parentEnv: Parent env vars (for preview branches)
  • build.env: Build-time environment variables

Sources: packages/cli-v3/src/commands/deploy.ts277-298

Image Build Strategies

The buildImage() function in packages/cli-v3/src/deploy/buildImage.ts53-99 supports two build strategies:

Local Builds (when isLocalBuild is true):

  • Uses Docker Buildx on developer machine via localBuildImage() packages/cli-v3/src/deploy/buildImage.ts133-266
  • Requires docker buildx version available
  • Authenticates to registry if authenticateToRegistry is true
  • Command: docker buildx build --platform={imagePlatform} --push
  • Supports custom builder name via builder option
  • Supports custom network mode via network option
  • Can optionally load image into local Docker via load option

Remote Builds (when isLocalBuild is false):

  • Offloads build to Depot API via remoteBuildImage() packages/cli-v3/src/deploy/buildImage.ts268-457
  • Uses externalBuildId and externalBuildToken from deployment
  • Creates build via depot.builds.create() with project ID
  • Polls for build completion with configurable timeout
  • Automatically pushed to registry
  • Faster builds with caching and parallelization

Both strategies produce the same image format:

  • Base tag: {imageTag} from deployment
  • Platform: Controlled by imagePlatform parameter
  • Registry: Determined by deployment registry configuration

Sources: packages/cli-v3/src/deploy/buildImage.ts53-457 packages/cli-v3/src/commands/deploy.ts327-445

Deployment Finalization and Task Indexing

After the image is built and pushed, the FinalizeDeploymentV2Service in apps/webapp/app/v3/services/finalizeDeploymentV2.server.ts11-164 handles finalization:

The finalization process:

  1. Image Reference Resolution: Either uses provided imageReference or fetches from Depot build manifest and resolves digest via getDeploymentImageRef() apps/webapp/app/v3/getDeploymentImageRef.server.ts28-170
  2. Status Update: Changes deployment status from BUILDING to DEPLOYING
  3. INDEX Trigger: Spawns ephemeral container with INDEX_TASKS=true environment variable
  4. Task Discovery: INDEX container imports task files and emits WorkerManifest
  5. Worker Creation: CreateBackgroundWorkerService creates database records for tasks, queues, and schedules

The WorkerManifest structure contains:

  • tasks: TaskResource[]: All discovered tasks with metadata
  • sourceFiles: BackgroundWorkerSourceFileMetadata[]: Source file mappings

Each TaskResource includes:

  • id: Task identifier
  • filePath: Source file location
  • exportName: Named export in file
  • queue: Queue configuration (name, concurrency)
  • retry: Retry policy configuration
  • machine: Machine preset requirements

Sources: apps/webapp/app/v3/services/finalizeDeploymentV2.server.ts11-164 apps/webapp/app/v3/getDeploymentImageRef.server.ts28-170 apps/webapp/app/v3/services/createBackgroundWorker.server.ts30-204

CreateBackgroundWorkerService

The CreateBackgroundWorkerService in apps/webapp/app/v3/services/createBackgroundWorker.server.ts30-286 creates database records for the deployed worker:

The service performs these operations in sequence:

  1. Version Calculation: Uses calculateNextBuildVersion() to increment semantic version (e.g., "v1.2.3" → "v1.2.4")
  2. Worker Record: Inserts BackgroundWorker with:
    • friendlyId: Generated unique identifier
    • contentHash: SHA-256 of bundled code
    • sdkVersion, cliVersion: Version metadata
    • engine: RunEngineVersion (V1 or V2)
    • supportsLazyAttempts: Feature flag
  3. File Mapping: Creates BackgroundWorkerFile records mapping contentHash to source file contents
  4. Queue Creation:
    • Checks for default queue configuration in project
    • Creates TaskQueue records (named or virtual per-task queues)
    • Associates queues with worker
  5. Task Creation: Creates BackgroundWorkerTask records with:
    • slug: Task identifier
    • queueConfig: Queue name and concurrency
    • retryConfig: Retry policy settings
    • machineConfig: Machine preset requirements
    • maxDurationInSeconds: Timeout configuration
  6. Schedule Sync:
    • Compares declarative schedules in code with existing DB schedules
    • Creates new schedules, updates modified ones, deactivates removed ones
    • Uses CheckScheduleService to validate and setup schedules
  7. Concurrency Update: Recalculates environment-level concurrency limits based on queue configurations
  8. Event Publishing: Broadcasts WORKER_READY event via projectPubSub to notify other services
  9. Run Scheduling: For V2 engine, calls scheduleEnqueueRunsForBackgroundWorker() to schedule pending runs

Sources: apps/webapp/app/v3/services/createBackgroundWorker.server.ts30-286

Docker Build Pipeline

The multi-stage Dockerfile produces an optimized production image with minimal attack surface and fast startup.

Dockerfile Stages

Sources: docker/Dockerfile1-116

Stage Details

StageFROMPurposeKey Operations
prunernode:20.11.1Extract workspaceturbo prune --scope=webapp --docker
basenode:20.11.1Layer caching foundationCopy package.json, lock files
dev-depsbaseDevelopment dependenciespnpm install with dev packages
production-depsbaseProduction dependenciespnpm install --prod, prisma generate
builderbaseBuild webappturbo build, upload sourcemaps
runnernode:20.11.1Final runtime imageCopy built assets, setup entrypoint

Sources: docker/Dockerfile1-116

Turbo Prune Optimization

The pruner stage uses Turborepo's prune command to extract only the webapp and its dependencies:

turbo prune --scope=webapp --docker

This produces a minimal out/ directory containing:

  • out/json/: All package.json files for webapp and dependencies
  • out/pnpm-lock.yaml: Filtered lockfile
  • out/full/: Full source code after pruning

The pruned workspace is significantly smaller than the full monorepo, reducing Docker context size and build time.

Sources: docker/Dockerfile6-12 turbo.json1-147

Entrypoint Script

The docker/scripts/entrypoint.sh1-52 script runs at container startup:

Key behaviors:

  • Wait for database: Uses wait-for-it.sh to ensure PostgreSQL is ready
  • Prisma migrations: Runs pnpm --filter @trigger.dev/database db:migrate:deploy
  • ClickHouse migrations: Uses Goose migrator if CLICKHOUSE_URL is set
  • Memory configuration: Sets --max-old-space-size from NODE_MAX_OLD_SPACE_SIZE (default 8192 MB)
  • Exec replacement: Uses exec to replace shell with Node.js process (proper signal handling)

Sources: docker/scripts/entrypoint.sh1-52

Environment Configuration

The webapp uses a comprehensive environment variable system defined in apps/webapp/app/env.server.ts1-688 with Zod validation.

Configuration Categories

Sources: apps/webapp/app/env.server.ts1-688

Critical Configuration

VariableTypeDefaultPurpose
DATABASE_URLPostgreSQL URLrequiredPrimary database connection
DATABASE_READ_REPLICA_URLPostgreSQL URLoptionalRead replica for queries
REDIS_HOSTstringoptionalPrimary Redis instance
SESSION_SECRETstringrequiredSession cookie signing
ENCRYPTION_KEY32-byte stringrequiredAPI key encryption
DEPLOY_REGISTRY_HOSTstringrequiredDocker registry host
DEPLOY_REGISTRY_NAMESPACEstring"trigger"Registry namespace
V4_DEPLOY_REGISTRY_*variousFalls back to V3Separate v4 registry config
MARQS_VISIBILITY_TIMEOUT_MSnumber900000 (15 min)Queue message timeout
RUN_ENGINE_WORKER_COUNTnumber4Number of run engine workers

Sources: apps/webapp/app/env.server.ts28-554

Redis Instance Segmentation

The platform uses separate Redis instances for different concerns to enable independent scaling:

Each Redis configuration includes:

  • *_HOST: Primary host
  • *_READER_HOST: Read replica host
  • *_PORT: Port number
  • *_USERNAME: Authentication username
  • *_PASSWORD: Authentication password
  • *_TLS_DISABLED: Disable TLS (default: false)
  • *_CLUSTER_MODE_ENABLED: Enable cluster mode (default: 0)

Sources: apps/webapp/app/env.server.ts95-237

BoolEnv Helper

The BoolEnv helper in apps/webapp/app/utils/boolEnv.ts2 provides Zod-based boolean parsing:

This is used throughout the environment schema to handle boolean flags consistently.

Sources: apps/webapp/app/env.server.ts2

CI/CD Integration

The deployment command is designed for integration with continuous integration pipelines.

GitHub Actions Integration

When running in GitHub Actions (detected via isCI from std-env), the deploy command in packages/cli-v3/src/commands/deploy.ts159-590:

  1. Fails Fast on Missing Token: Checks for TRIGGER_ACCESS_TOKEN early in CI environments and provides helpful error message with documentation link packages/cli-v3/src/commands/deploy.ts177-192
  2. Streams Logs to Stdout: Uses console.log() instead of spinner updates for build logs
  3. Sets GitHub Outputs: Calls setGithubActionsOutputAndEnvVars() with deployment metadata
  4. Provides URLs: Sets environment variables and outputs for use in subsequent workflow steps

Sources: packages/cli-v3/src/commands/deploy.ts159-590 packages/cli-v3/src/utilities/githubActions.ts1-50

CI-specific Behaviors

The command detects CI via the isCI constant from std-env:

When isCI is true:

  • Log messages use console.log() instead of spinner updates
  • No interactive prompts
  • Full log output without throttling
  • GitHub Actions outputs set automatically

Sources: packages/cli-v3/src/commands/deploy.ts9 packages/cli-v3/src/commands/deploy.ts397-437

GitHub Actions Output Format

The setGithubActionsOutputAndEnvVars() function sets these outputs:

Output VariableExample ValueDescription
TRIGGER_DEPLOYMENT_VERSION"v1.2.3"Semantic version
TRIGGER_VERSION"v1.2.3"Alias for version
TRIGGER_DEPLOYMENT_SHORT_CODE"abc123"Short identifier
TRIGGER_DEPLOYMENT_URLhttps://cloud.trigger.dev/...Dashboard URL
TRIGGER_TEST_URLhttps://cloud.trigger.dev/.../testTest page URL

These can be used in subsequent workflow steps:

Sources: packages/cli-v3/src/commands/deploy.ts584-590

Build Failure Handling

When builds fail, the command in packages/cli-v3/src/commands/deploy.ts449-521:

  1. Catches Build Errors: Wraps image build in try-catch block
  2. Parses Logs: Uses checkLogsForErrors() and checkLogsForWarnings() from packages/cli-v3/src/deploy/logs.ts1-150
  3. Categorizes Issues: Distinguishes warnings from fatal errors
  4. Saves Logs: Optionally saves full build logs to disk with saveLogs() based on --save-logs flag
  5. Calls failDeployment(): Makes API call to POST /api/v1/deployments/:id/fail with:
    • error: Serialized error details
    • errorData: Additional context (stack trace, stderr)
  6. Pretty Prints Errors: Uses prettyError() to format error messages for terminal output
  7. Throws SkipLoggingError: Prevents double-logging of error messages in CLI wrapper

The failure flow ensures deployments are marked as FAILED status in the database even if the CLI process is interrupted. The FailDeploymentService in apps/webapp/app/v3/services/failDeployment.server.ts1-100 updates the deployment record and cleans up any associated resources.

Sources: packages/cli-v3/src/commands/deploy.ts449-521 packages/cli-v3/src/deploy/logs.ts1-150

Webapp Server Process

The webapp server in apps/webapp/server.ts1-270 runs as either a single process or in cluster mode with multiple workers.

Cluster Mode Architecture

Cluster configuration:

  • Enabled via ENABLE_CLUSTER=1
  • Worker count from WEB_CONCURRENCY or CLUSTER_WORKERS or CPU count
  • Primary process forwards SIGTERM/SIGINT to workers
  • Workers exit with code 0 for intentional shutdown
  • Primary waits up to GRACEFUL_SHUTDOWN_TIMEOUT (default 30s) for workers to exit

Sources: apps/webapp/server.ts18-90

Express Middleware Stack

The Express app configures middleware in this order:

Sources: apps/webapp/server.ts91-230

Request Context Tracking

The server uses runWithHttpContext() from apps/webapp/app/services/httpAsyncStorage.server.ts14 to track request metadata:

This creates an AsyncLocalStorage context available throughout request processing for logging and tracing.

Sources: apps/webapp/server.ts145-153

Graceful Shutdown

Worker processes handle shutdown signals gracefully:

The graceful shutdown sequence:

  1. Catch SIGTERM signal
  2. Emit beforeExit event to Socket.IO clients
  3. Close Socket.IO server (stops accepting new connections)
  4. Close HTTP server (waits for in-flight requests)
  5. Force exit after GRACEFUL_SHUTDOWN_TIMEOUT ms (default 30s)

Sources: apps/webapp/server.ts192-230

Server Initialization

When the HTTP server starts, it:

  1. Mounts Socket.IO: If socketIo module exists, attach to HTTP server
  2. Mounts WebSocket: If wss module exists, handle upgrade requests
  3. Starts listening: Bind to REMIX_APP_PORT or PORT (default 3000)
  4. Broadcasts dev ready: In development, calls broadcastDevReady() for HMR

The server can be disabled entirely with HTTP_SERVER_DISABLED=true for testing.

Sources: apps/webapp/server.ts119-230