Triginn is a self-hosted async infrastructure engine. One binary replaces your workflow runner, job queue, cron scheduler, and event bus — with zero external brokers and RPO=0 durability.
import { z } from 'zod'
import { workflow, cron, task, onEvent, TriginnClient, TriginnWorker } from '@triginn/sdk'
// Durable workflow — survives crashes, replays from WAL
const processOrder = workflow('process-order', {
schema: z.object({ orderId: z.string() }),
run: async (payload, ctx, step) => {
const charged = await step.run('charge-card', async () => {
return chargeCard(payload.orderId)
})
await step.sleep('wait-for-confirmation', '30s')
await step.run('send-receipt', async () => {
return sendReceipt(payload.orderId, charged.amount)
})
},
})
// Cron — persisted in WAL, fires without a sidecar
const dailyReport = cron('daily-report', '0 9 * * *', async (ctx, step) => {
await step.run('generate', () => generateReport())
})
// Background task — fire-and-forget with retry policy
const sendEmail = task('send-email', {
schema: z.object({ to: z.string().email() }),
run: async (payload) => { await mailer.send(payload.to) },
retryPolicy: { maxAttempts: 3, backoff: 'exponential', baseDelayMs: 1000 },
})
// Event-triggered — start a workflow when an event arrives
const orderRegistration = onEvent('order.placed', processOrder)
const client = new TriginnClient({
serverUrl: process.env.TRIGINN_NODE_URL ?? 'http://localhost:7800',
token: () => process.env.TRIGINN_TOKEN!,
namespace: 'production',
})
const worker = new TriginnWorker(client, [processOrder, dailyReport, sendEmail, orderRegistration])
await worker.start() Replaces
Built for backend engineers who want control without the operational overhead of four separate services.
Single Go binary. Pebble WAL for persistence. No Kafka, no Redis, no Postgres, no NATS. Nothing to manage.
Crash-safe, replay-safe execution. Every step is written to the WAL before it runs. RPC-0 durability by default.
Fire-and-forget jobs with configurable retry policies and exponential backoff — no BullMQ, no queue infra.
Cron schedules persist in the WAL and fire without a sidecar process. Timezone-aware. Catch-up policy configurable.
Ingest any event and start the right workflow automatically. Schema-validated at ingest time via Zod.
Deploy new workflow versions while old runs are still executing. version() guards keep WAL history consistent.
Namespace isolation with token-based auth. Run multiple teams on one engine — data never crosses namespace boundaries.
ESLint plugin catches non-deterministic code at write time — before it reaches production.
Helm chart included. One command deploys the full engine to your cluster. Scales horizontally with your workers.
From code to production in three steps.
Use workflow(), task(), cron(), and onEvent() to declare your async logic. The ESLint plugin enforces determinism as you type.
Install via the Helm chart or Docker. One Go binary, one WAL directory. No Redis, no NATS, no Postgres. Your infra only.
TriginnWorker connects to the engine via gRPC, receives activations, replays from WAL history, and runs your handlers durably.
Four tools, one deployment, one WAL, one bill.
| Triginn | trigger.dev | BullMQ | NATS JetStream | Valkey | |
|---|---|---|---|---|---|
| Self-hosted | ✓ | ✓ | ✓ | ✓ | ✓ |
| No external broker required | ✓ | ✗ | ✗ | ✗ | ✗ |
| Durable workflows | ✓ | ✓ | ✗ | ✗ | ✗ |
| Background tasks with retry | ✓ | ✓ | ✓ | ✓ | ✗ |
| Built-in cron scheduling | ✓ | ✓ | ✗ | ✓ | ✗ |
| Event-triggered workflows | ✓ | ✓ | ✗ | ✓ | ✗ |
| In-flight version migration | ✓ | ✗ | ✗ | ✗ | ✗ |
| TypeScript SDK | ✓ | ✓ | ✓ | ✓ | ✗ |
| Multi-tenant namespaces | ✓ | ✗ | ✗ | ✓ | ✗ |
| RPO=0 (fsync WAL) | ✓ | ✗ | ✗ | ✗ | ✗ |
Triginn is proprietary software licensed per deployment. Pricing available on request.
Triginn is deployed as a compiled binary on your Kubernetes cluster or bare metal. Your workflow data never leaves your infrastructure. The source code is not distributed — you get a hardened, production-ready binary with a commercial support SLA.
Deployment model
Deploy Triginn on your cluster and shut down your workflow runner, job queue, cron scheduler, and event bus — for good.