Inngest Setup This skill sets up Inngest in a TypeScript project from scratch, covering installation, client configuration, connection modes, and local development. These skills are focused on TypeScript. For Python or Go, refer to the Inngest documentation for language-specific guidance. Core concepts apply across all languages. Prerequisites Node.js 18+ (Node.js 22.4+ r ecommended for WebSocket support) TypeScript project Package manager (npm, yarn, pnpm, or bun) Step 1: Install the Inngest SDK Install the inngest npm package in your project: npm install inngest
or
yarn add inngest
or
pnpm add inngest
or
- bun
- add
- inngest
- Step 2: Create an Inngest Client
- Create a shared client file that you'll import throughout your codebase:
- // src/inngest/client.ts
- import
- {
- Inngest
- }
- from
- "inngest"
- ;
- export
- const
- inngest
- =
- new
- Inngest
- (
- {
- id
- :
- "my-app"
- // Unique identifier for your application (hyphenated slug)
- }
- )
- ;
- Key Configuration Options
- id
- (required): Unique identifier for your app. Use a hyphenated slug like
- "my-app"
- or
- "user-service"
- eventKey
-
- Event key for sending events (prefer
- INNGEST_EVENT_KEY
- env var)
- env
-
- Environment name for Branch Environments
- isDev
-
- Force Dev mode (
- true
- ) or Cloud mode (
- false
- )
- logger
-
- Custom logger instance (e.g. winston, pino) — enables
- logger
- in function context
- middleware
-
- Array of middleware (see
- inngest-middleware
- skill)
- schemas
- Use
EventSchemas
for typed events (see
inngest-events
skill)
Typed Events with EventSchemas
import
{
Inngest
,
EventSchemas
}
from
"inngest"
;
type
Events
=
{
"user/signup.completed"
:
{
data
:
{
userId
:
string
;
email
:
string
;
plan
:
"free"
|
"pro"
;
}
;
}
;
"order/placed"
:
{
data
:
{
orderId
:
string
;
amount
:
number
;
}
;
}
;
}
;
export
const
inngest
=
new
Inngest
(
{
id
:
"my-app"
,
schemas
:
new
EventSchemas
(
)
.
fromRecord
<
Events
( ) } ) ; // Now event data is fully typed in functions: // inngest.createFunction({ id: "handle-signup" }, { event: "user/signup.completed" }, // async ({ event }) => { event.data.userId / typed as string / } // ); Environment Variables Setup Set these environment variables in your .env file or deployment environment:
Required for production
INNGEST_EVENT_KEY=your-event-key-here INNGEST_SIGNING_KEY=your-signing-key-here
Force dev mode during local development
INNGEST_DEV=1
Optional - custom dev server URL (default: http://localhost:8288)
- INNGEST_BASE_URL=http://localhost:8288
- ⚠️ Common Gotcha
-
- Never hardcode keys in your source code. Always use environment variables for
- INNGEST_EVENT_KEY
- and
- INNGEST_SIGNING_KEY
- .
- Step 3: Choose Your Connection Mode
- Inngest supports two connection modes:
- Mode A: Serve Endpoint (HTTP)
- Best for serverless platforms (Vercel, Lambda, etc.) and existing APIs.
- Mode B: Connect (WebSocket)
- Best for container runtimes (Kubernetes, Docker) and long-running processes.
- Step 4A: Serving an Endpoint (HTTP Mode)
- Create an API endpoint that exposes your functions to Inngest:
- // For Next.js App Router: src/app/api/inngest/route.ts
- import
- {
- serve
- }
- from
- "inngest/next"
- ;
- import
- {
- inngest
- }
- from
- "../../../inngest/client"
- ;
- import
- {
- myFunction
- }
- from
- "../../../inngest/functions"
- ;
- export
- const
- {
- GET
- ,
- POST
- ,
- PUT
- }
- =
- serve
- (
- {
- client
- :
- inngest
- ,
- functions
- :
- [
- myFunction
- ]
- }
- )
- ;
- // For Next.js Pages Router: pages/api/inngest.ts
- import
- {
- serve
- }
- from
- "inngest/next"
- ;
- import
- {
- inngest
- }
- from
- "../../inngest/client"
- ;
- import
- {
- myFunction
- }
- from
- "../../inngest/functions"
- ;
- export
- default
- serve
- (
- {
- client
- :
- inngest
- ,
- functions
- :
- [
- myFunction
- ]
- }
- )
- ;
- // For Express.js
- import
- express
- from
- "express"
- ;
- import
- {
- serve
- }
- from
- "inngest/express"
- ;
- import
- {
- inngest
- }
- from
- "./inngest/client"
- ;
- import
- {
- myFunction
- }
- from
- "./inngest/functions"
- ;
- const
- app
- =
- express
- (
- )
- ;
- app
- .
- use
- (
- express
- .
- json
- (
- {
- limit
- :
- "10mb"
- }
- )
- )
- ;
- // Required for Inngest, increase limit for larger function state
- app
- .
- use
- (
- "/api/inngest"
- ,
- serve
- (
- {
- client
- :
- inngest
- ,
- functions
- :
- [
- myFunction
- ]
- }
- )
- )
- ;
- 🔧 Framework-Specific Notes
- :
- Express
-
- Must use
- express.json({ limit: "10mb" })
- middleware to support larger function state.
- Fastify
-
- Use
- fastifyPlugin
- from
- inngest/fastify
- Cloudflare Workers
-
- Use
- inngest/cloudflare
- AWS Lambda
-
- Use
- inngest/lambda
- For all other frameworks, check the
- serve
- reference here:
- https://www.inngest.com/docs-markdown/learn/serving-inngest-functions
- ⚠️ Common Gotcha
-
- Always use
- /api/inngest
- as your endpoint path. This enables automatic discovery. If you must use a different path, you'll need to configure discovery manually with the
- -u
- flag.
- Step 4B: Connect as Worker (WebSocket Mode)
- For long-running applications that maintain persistent connections:
- // src/worker.ts
- // Note: inngest/connect requires inngest SDK v3.27+
- import
- {
- connect
- }
- from
- "inngest/connect"
- ;
- import
- {
- inngest
- }
- from
- "./inngest/client"
- ;
- import
- {
- myFunction
- }
- from
- "./inngest/functions"
- ;
- (
- async
- (
- )
- =>
- {
- const
- connection
- =
- await
- connect
- (
- {
- apps
- :
- [
- {
- client
- :
- inngest
- ,
- functions
- :
- [
- myFunction
- ]
- }
- ]
- ,
- instanceId
- :
- process
- .
- env
- .
- HOSTNAME
- ,
- // Unique worker identifier
- maxWorkerConcurrency
- :
- 10
- // Max concurrent steps
- }
- )
- ;
- console
- .
- log
- (
- "Worker connected:"
- ,
- connection
- .
- state
- )
- ;
- // Graceful shutdown handling
- await
- connection
- .
- closed
- ;
- console
- .
- log
- (
- "Worker shut down"
- )
- ;
- }
- )
- (
- )
- ;
- Requirements for Connect Mode
- :
- Node.js 22.4+ (or Deno 1.4+, Bun 1.1+) for WebSocket support
- Long-running server environment (not serverless)
- INNGEST_SIGNING_KEY
- and
- INNGEST_EVENT_KEY
- for production
- Set the
- appVersion
- parameter on the
- Inngest
- client for production to support rolling deploys
- Step 5: Organizing with Apps
- As your system grows, organize functions into logical apps:
- // User service
- const
- userService
- =
- new
- Inngest
- (
- {
- id
- :
- "user-service"
- }
- )
- ;
- // Payment service
- const
- paymentService
- =
- new
- Inngest
- (
- {
- id
- :
- "payment-service"
- }
- )
- ;
- // Email service
- const
- emailService
- =
- new
- Inngest
- (
- {
- id
- :
- "email-service"
- }
- )
- ;
- Each app gets its own section in the Inngest dashboard and can be deployed independently. Use descriptive, hyphenated IDs that match your service architecture.
- ⚠️ Common Gotcha
- Changing an app's id creates a new app in Inngest. Keep IDs consistent across deployments. Step 6: Local Development with inngest-cli Start the Inngest Dev Server for local development:
Auto-discover your app on common ports/endpoints
npx --ignore-scripts
false inngest-cli@latest dev
Specify your app's URL manually
npx --ignore-scripts
false inngest-cli@latest dev -u http://localhost:3000/api/inngest
Custom port for dev server
npx --ignore-scripts
false inngest-cli@latest dev -p 9999
Disable auto-discovery
npx --ignore-scripts
false inngest-cli@latest dev --no-discovery -u http://localhost:3000/api/inngest
Multiple apps
npx --ignore-scripts
false inngest-cli@latest dev -u http://localhost:3000/api/inngest -u http://localhost:4000/api/inngest The dev server will be available at http://localhost:8288 by default. Configuration File (Optional) Create inngest.json for complex setups: { "sdk-url" : [ "http://localhost:3000/api/inngest" , "http://localhost:4000/api/inngest" ] , "port" : 8289 , "no-discovery" : true } Environment-Specific Setup Local Development INNGEST_DEV=1
No keys required in dev mode
- Production
- INNGEST_EVENT_KEY=evt_your_production_event_key
- INNGEST_SIGNING_KEY=signkey_your_production_signing_key
- Custom Dev Server Port
- INNGEST_DEV=1
- INNGEST_BASE_URL=http://localhost:9999
- If your app runs on a non-standard port (not 3000), make sure the dev server can reach it by specifying the URL with
- -u
- flag.
- Common Issues & Solutions
- Port Conflicts
-
- If port 8288 is in use, specify a different port:
- -p 9999
- Auto-discovery Not Working
-
- Use manual URL specification:
- -u http://localhost:YOUR_PORT/api/inngest
- Signature Verification Errors
-
- Ensure
- INNGEST_SIGNING_KEY
- is set correctly in production
- WebSocket Connection Issues
-
- Verify Node.js version 22.4+ for connect mode
- Docker Development
- Use host.docker.internal for app URLs when running dev server in Docker Next Steps Create your first Inngest function with inngest.createFunction() Test functions using the dev server's "Invoke" button Send events with inngest.send() to trigger functions Deploy to production with proper environment variables See inngest-middleware for adding logging, error tracking, and other cross-cutting concerns Monitor functions in the Inngest dashboard The dev server automatically reloads when you change functions, making development fast and iterative.