logo
icon

Inngest

Self-hosted Inngest — a durable execution engine for reliable background jobs and AI workflows. Includes PostgreSQL and Redis.

PlatformZeabur
Deployed3
PublisherzeaburZeabur
Deployed3 times
PublisherzeaburZeabur
Created2026-04-16
Services
service icon
service icon
service icon
Tags
Developer ToolsBackground JobsWorkflow

Inngest — Self-Hosted

Inngest is an open-source durable execution engine that lets you write reliable background jobs, scheduled functions, and AI workflows with built-in retries, concurrency control, and observability.

This template deploys a self-hosted Inngest instance with PostgreSQL (state persistence) and Redis (queue and cache) in a single click.

Services

ServicePortPurpose
Inngest Dashboard & API8288 (HTTP)UI, event ingestion, REST API
Inngest Connect Gateway8289 (HTTP/WSS)WebSocket gateway for SDK workers
PostgreSQL5432Durable state storage
Redis6379Queue and cache

Required Setup Before Deploying

You need two hex strings (even number of characters, using 0-9 and a-f only).

Generate on macOS/Linux:

openssl rand -hex 16

Use one value for Event Key and another for Signing Key.

⚠️ Security Warning

By design, Inngest self-hosted does not protect the dashboard UI or GraphQL API with authentication. The source code only applies the signing key middleware to SDK-facing endpoints:

EndpointProtected
Dashboard UI❌ Public
GraphQL API (/v0/gql)❌ Public — anyone can query all apps, functions, and events
Event ingestion (/e/*)✅ Requires Event Key
SDK sync (/fn/register)✅ Requires Signing Key
Connect WebSocket✅ Requires Signing Key

Recommended: do not expose the Dashboard domain publicly. Place it behind a VPN, IP allowlist, or HTTP Basic Auth proxy. The Connect Gateway domain (port 8289) must remain publicly accessible for SDK workers to connect.

Connecting SDK Workers

After deployment, configure your Inngest SDK to point to your self-hosted instance:

const inngest = new Inngest({
  id: "my-app",
  baseUrl: "https://YOUR_DOMAIN",   // Dashboard domain (port 8288)
  eventKey: "YOUR_EVENT_KEY",
  signingKey: "YOUR_SIGNING_KEY",
});

For Connect (persistent WebSocket workers), override the gateway URL with your Connect domain:

import { connect } from "inngest/connect";

// ⚠️ Use `triggers` (plural array), NOT `trigger` (singular)
const myFn = inngest.createFunction(
  { id: "my-fn", triggers: [{ event: "my/event" }] },
  async ({ event, step }) => { /* ... */ }
);

await connect({
  apps: [{ client: inngest, functions: [myFn] }],
  gatewayUrl: "wss://YOUR_CONNECT_DOMAIN/v0/connect",
});

Note: The Connect gateway WebSocket path is /v0/connect. Always use triggers: [...] (plural array) when defining functions — using trigger: (singular) will result in empty triggers and functions will never execute.

License

Inngest is open-source under the Apache 2.0 License.