Trigger.dev V2 positions itself as a Temporal alternative for TypeScript developers who want durable execution without running a separate Go-based orchestrator. The pivot from “Zapier alternative” (745 points on Show HN in February 2023) to “Temporal alternative” (172 points in October 2023) reflects real demand for workflow primitives that live in the same language as application code.
The core question: can you get exactly-once semantics, retries, and long-running task orchestration without adopting Temporal’s architecture (separate workflow engine, gRPC protocol, Go runtime)? Trigger.dev bets you can by embedding orchestration logic directly into TypeScript and offloading state persistence to a managed control plane.
Architecture: Embedded Orchestration vs. Separate Engine
Temporal’s model:
- Workflows run in a separate Go-based engine
- Application code communicates via gRPC
- State lives in a dedicated database (Cassandra, PostgreSQL, or MySQL)
- Workers poll task queues and execute activities
- Workflow history is append-only and replayed for recovery
Trigger.dev’s model:
- Workflows are TypeScript functions decorated with
task() - State persistence happens server-side via Trigger.dev’s control plane
- No separate engine to deploy or maintain
- Workers are Node.js processes that connect to the platform via WebSocket or HTTP long-polling
- Retry and timeout logic is declared inline with the task definition
The key difference: Temporal treats workflows as code that must be deterministic and replayable. Trigger.dev treats tasks as durable API calls with built-in retry and observability.
Durable Execution Without Replay
Temporal achieves durability through event sourcing. Every workflow decision is logged, and the engine replays history to reconstruct state after a crash. This requires strict determinism: no random numbers, no direct I/O, no non-deterministic library calls.
Trigger.dev skips replay. Instead, it checkpoints task state at explicit boundaries (before and after each step) and stores it server-side. If a worker crashes, the platform resumes from the last checkpoint. This trades Temporal’s fine-grained recovery for simpler developer ergonomics.
Example task definition:
import { task } from "@trigger.dev/sdk/v3";
export const processOrder = task({
id: "process-order",
retry: {
maxAttempts: 3,
factor: 2,
minTimeout: 1000,
maxTimeout: 10000,
},
run: async (payload: { orderId: string }) => {
// Step 1: Charge payment (checkpointed)
const charge = await stripe.charges.create({
amount: payload.amount,
currency: "usd",
source: payload.token,
});
// Step 2: Update inventory (checkpointed)
await db.inventory.decrement({
where: { sku: payload.sku },
data: { quantity: 1 },
});
// Step 3: Send confirmation (checkpointed)
await sendEmail({
to: payload.email,
subject: "Order confirmed",
body: `Your order ${payload.orderId} is confirmed.`,
});
return { chargeId: charge.id };
},
});
Each await is a potential checkpoint. If the worker dies after charging the payment but before updating inventory, Trigger.dev resumes at the inventory step. No replay, no event log.
Retry Policies and Timeout Boundaries
Both systems offer configurable retries, but the implementation differs.
| Feature | Temporal | Trigger.dev |
|---|---|---|
| Retry strategy | Exponential backoff with jitter | Exponential backoff with jitter |
| Timeout granularity | Per-activity, per-workflow, schedule-to-close | Per-task, per-step |
| Idempotency | Developer must ensure activity idempotency | Developer must ensure step idempotency |
| Failure visibility | Workflow history in UI | Task run logs in dashboard |
| Dead letter queue | Manual via continue-as-new | Automatic after max attempts |
Temporal’s activity timeouts are more granular. You can set ScheduleToStart, StartToClose, ScheduleToClose, and Heartbeat timeouts independently. Trigger.dev collapses this into a single task-level timeout with optional step-level overrides.
State Persistence and Observability
Temporal stores workflow state in your database. You control the schema, backups, and scaling. Trigger.dev stores task state in its managed control plane. You get observability out of the box (traces, logs, metrics) but lose direct database access.
Observability in Trigger.dev:
- Real-time task execution traces
- Automatic retry and failure logs
- Webhook delivery for task completion
- Built-in dashboard with filtering and search
Observability in Temporal:
- Workflow history in Temporal Web UI
- Custom metrics via Prometheus
- Workflow search via Elasticsearch (optional)
- Event export to external systems
If you need to query task state programmatically (e.g., “show me all failed orders in the last hour”), Temporal’s database-backed approach is more flexible. Trigger.dev requires API calls to the control plane.
Deployment Shape and Operational Complexity
Temporal deployment:
- Run Temporal Server (Go binary or Helm chart)
- Provision database (Cassandra, PostgreSQL, MySQL)
- Deploy worker processes (your application code)
- Configure task queues and namespaces
- Set up monitoring (Prometheus, Grafana)
Trigger.dev deployment:
- Sign up for Trigger.dev Cloud or self-host the control plane
- Deploy worker processes (your application code)
- Set environment variables for API key and endpoint
Trigger.dev’s managed control plane eliminates the database and server setup. Self-hosting is possible but adds operational overhead similar to Temporal.
Security and Isolation Boundaries
Temporal workflows run in your infrastructure. You control network boundaries, secrets management, and access policies. Trigger.dev tasks run in your workers but communicate with a third-party control plane. This introduces trust boundaries:
- Task payloads transit through Trigger.dev’s servers
- Secrets must be injected at runtime (not stored in the platform)
- Network policies must allow outbound connections to Trigger.dev
For regulated environments (healthcare, finance), Temporal’s self-contained architecture may be easier to audit. Trigger.dev’s cloud model works when you trust the platform or self-host.
Failure Modes and Recovery
Temporal failure modes:
- Worker crashes: workflow resumes from last decision
- Database outage: workflows pause until database recovers
- Network partition: workers retry task queue polling
- Corrupted workflow history: manual intervention required
Trigger.dev failure modes:
- Worker crashes: task resumes from last checkpoint
- Control plane outage: tasks pause until platform recovers
- Network partition: workers retry WebSocket connection
- Corrupted task state: platform handles recovery or marks task as failed
Temporal’s event sourcing provides stronger durability guarantees. If the database is intact, you can always reconstruct workflow state. Trigger.dev’s checkpoint model is simpler but less resilient to control plane failures.
When TypeScript-Native Wins
Trigger.dev makes sense when:
- Your team is TypeScript-first and wants to avoid Go
- You need durable execution but not Temporal’s full feature set
- You prefer managed infrastructure over self-hosting
- Your workflows are mostly linear with occasional retries
Temporal makes sense when:
- You need fine-grained timeout control and complex branching logic
- You want full control over state persistence and database schema
- You require multi-language support (Go, Java, Python, PHP)
- You need to audit every workflow decision for compliance
Technical Verdict
Trigger.dev trades Temporal’s operational complexity for developer ergonomics. You get durable execution, retries, and observability without deploying a separate orchestrator. The cost is less control over state persistence and tighter coupling to the platform.
Use Trigger.dev when you want workflow primitives in TypeScript without infrastructure overhead. Use Temporal when you need full control over durability guarantees and can justify the operational cost.
For agent orchestration, Trigger.dev’s checkpoint model works well for linear pipelines (fetch data, call LLM, store result). Temporal’s replay model is better for complex branching logic (conditional tool calls, parallel fan-out, human-in-the-loop).