Skip to main content

How to Self-Host Trigger.dev in 2026

·OSSAlt Team
trigger.devbackground-jobsself-hostedautomationworkflows
Share:

What Trigger.dev Is Best At

Trigger.dev (Apache-2.0, ~14.5K stars) is a code-first background job and workflow platform built with TypeScript, React, and Node. Developers define tasks as TypeScript functions — retries, concurrency, schedules, and long-running resumable flows are primitives, not plugins. Think "Sidekiq + Temporal + Zapier internals" for teams that want to own their automation surface without running a heavy workflow engine.

Use Trigger.dev when:

  • You want background jobs defined in the same repo as your app, not in a visual builder
  • Tasks can take minutes to hours (durable execution, resumability)
  • You need scheduled jobs, webhooks, event triggers, and queues in one system
  • You would otherwise stitch together BullMQ, a cron daemon, and custom retry logic

Core Architecture and Prerequisites

The self-hosted stack has four moving pieces:

  • Web app — dashboard, API, task registration
  • Workers — execute task runs, pull from queues, report results
  • PostgreSQL — durable task state, run history, schedules
  • Redis — coordination, rate limiting, short-term queue state

For larger deployments, an object store (S3-compatible) holds task artifacts and logs. The Trigger.dev v3+ architecture emphasizes container-based workers so task code is isolated from the control plane; plan for a container registry if you want the most flexible deployment.

Sizing rule of thumb. A single worker VM with 2 vCPU / 4 GB RAM comfortably handles low-throughput workloads (sub-100 concurrent runs, short jobs). Long-running jobs, video processing, or AI pipelines push worker memory up quickly — scale workers horizontally rather than vertically.

Docker / Self-Host Deployment Flow

The official self-host reference uses Docker Compose:

git clone https://github.com/triggerdotdev/trigger.dev
cd trigger.dev/hosting/docker
cp .env.example .env
# edit secrets, database password, APP_ORIGIN
docker compose up -d

This brings up the webapp, Postgres, and Redis, plus a worker pool. In production:

  1. Move Postgres and Redis to managed services (RDS/Neon, Upstash/Elasticache)
  2. Run the webapp behind a reverse proxy with TLS
  3. Deploy workers as a separate, horizontally scalable service
  4. Configure container registry credentials if using image-based task deployment

For Dokploy, Coolify, or Kubernetes, split the compose file into two deployments — one for the web app, one for workers — so you can scale workers independently.

Worker Concurrency and Queue Sizing

Concurrency on Trigger.dev lives at three levels: per-task, per-queue, and per-worker. Default settings will run many tasks at once, which is usually the wrong choice for anything hitting a downstream rate-limited API.

Rules that have held up in production:

  • Set per-task concurrency explicitly for anything that calls external APIs
  • Keep worker CPU oversubscription low — background jobs often block on I/O but spike on JSON parsing and hashing
  • Separate workers into pools by workload class (fast/short vs slow/long) so a 10-minute task cannot starve a 100ms task

Measure before optimizing: the built-in dashboard exposes run duration percentiles, queue depth, and retry counts, which are enough for a first round of tuning.

Secrets, Webhooks, and Observability

Secrets are stored encrypted in the Trigger.dev database. Teams with stricter requirements can front them with an external secret manager and inject at worker boot.

Webhooks into Trigger.dev tasks are first-class — incoming webhooks trigger task runs, and outgoing HTTP calls inside tasks get automatic retry and timeout handling. Always sign webhooks at the edge (Cloudflare Worker, nginx) before they reach the task runtime.

Observability hooks into OpenTelemetry; traces and logs export to any OTLP-compatible backend. Pair it with a log sink (Loki, CloudWatch, Axiom) so you can search across runs, not just the latest dashboard view.

Backups, Upgrades, and Failure Modes

  • Backups: nightly pg_dump of the Trigger.dev database, plus retention on object storage for task artifacts.
  • Upgrades: pin image tags per environment. Trigger.dev iterates quickly; always run schema migrations on a staging copy before production.
  • Worker crashes: durable execution means an interrupted task resumes on another worker. Test it — run a 5-minute task, kill the worker mid-run, confirm the task completes on another.
  • Database pressure: task history grows fast. Tune retention on completed runs; keep failures longer than successes.
  • Redis eviction: never run Trigger.dev's Redis with allkeys-lru. Queue state must be durable for the length of a run.

When to Pick Trigger.dev Over n8n

Trigger.dev and n8n overlap at a glance — both run workflows, both handle webhooks and schedules, both are open source. The split is audience:

  • Trigger.dev belongs in an engineering org. Tasks are TypeScript; Git is the source of truth; code review and CI apply to automations just like product code. Use it when reliability, resumability, and testability matter more than non-engineer access.
  • n8n belongs in an automation-heavy team where non-engineers build flows. The visual canvas is a feature, not a liability.

If both apply, it is reasonable to run both: Trigger.dev for app-internal jobs, n8n for cross-tool automation that marketing, ops, and support touch. For a head-to-head comparison, see Trigger.dev vs n8n.

For the platform layer underneath, see how to self-host Dokploy and the self-hosting backup guide — both apply directly to Trigger.dev operations.

The SaaS-to-Self-Hosted Migration Guide (Free PDF)

Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.

Join 300+ self-hosters. Unsubscribe in one click.