Connect
These docs are part of a developer preview for Inngest's connect
API. Learn more about the developer preview here.
The connect
API allows your app to create an outbound persistent connection to Inngest. Each app can establish multiple connections to Inngest, which enable you to scale horizontally across multiple workers. The key benefits of using connect
compared to serve
are:
- Lowest latency - Persistent connections enable the lowest latency between your app and Inngest.
- Elastic horizontal scaling - Easily add more capacity by running additional workers.
- Ideal for container runtimes - Deploy on Kubernetes or ECS without the need of a load balancer for inbound traffic
- Simpler long running steps - Step execution is not bound by platform http timeouts.
Getting started
Using connect
with your app is simple. Using each SDK's "connect" method only requires a list of functions that are available to be executed. (Note: Python is not yet supported; upvote and join the waiting list here)
Here is a one-file example of a fully-functioning app that connects to Inngest.
import { Inngest } from 'inngest'
import { connect } from 'inngest/connect';
import { ConnectionState } from 'inngest/components/connect/types';
const inngest = new Inngest({
id: 'my-app'
});
const handleSignupFunction = inngest.createFunction(
{ id: 'handle-signup' },
{ event: 'user.created'}
async ({ event, step }) => {
console.log('Function called', event);
}
);
(async () => {
const connection = await connect({
apps: [{ client: inngest, functions: [handleSignupFunction] }]
});
console.log('Worker: connected', connection);
})();
How does it work?
The connect
API establishes a persistent WebSocket connection to Inngest. Each connection can handle executing multiple functions and steps concurrently. Each app can create multiple connections to Inngest enabling horizontal scaling. Additionally, connect has the following features:
- Automatic re-connections - The connection will automatically reconnect if it is closed.
- Graceful shutdown - The connection will gracefully shutdown when the app receives a signal to terminate (
SIGTERM
). New steps will not be accepted after the connection is closed, and existing steps will be allowed to complete. - Worker-level maximum concurrency (Coming soon) - Each worker can configure the maximum number of concurrent steps it can handle. This allows Inngest to distribute load across multiple workers and not overload a single worker.
Local development
During local development, set the INNGEST_DEV=1
environment variable to enable local development mode. This will cause the SDK to connect to the Inngest dev server. When your worker process is running it will automatically connect to the dev server and sync your functions' configurations.
No signing or event keys are required in local development mode.
Deploying to production
The connect
API is currently in developer preview and is not yet recommended for critical production workloads. We recommend deploying to a staging environment first prior to deploying to production.
Set signing and event keys
To enable your application to securely connect to Inngest, you must set the INNGEST_SIGNING_KEY
and INNGEST_EVENT_KEY
environment variables.
These keys can be found in the Inngest Dashboard. Learn more about Event keys and Signing Keys.
Set your app version
The appVersion
is used to identify the version of your app that is connected to Inngest. This allows Inngest to support rolling deploys where multiple versions of your app may be connected to Inngest.
When a new version of your app is connected to Inngest, the functions' configurations are synced to Inngest. When a new version is connected, Inngest update the function configuration in your environment and starts routing new function runs to the latest version.
You can set the appVersion
to whatever you want, but we recommend using something that automatically changes with each deploy, like a git commit sha or Docker image tag.
// You can set the app version to any environment variable, you might use
// a build number ('v2025.02.12.01'), git commit sha ('f5a40ff'), or
// a custom value ('my-app-v1').
const inngest = new Inngest({
id: 'my-app',
appVersion: process.env.MY_APP_VERSION, // Use any environment variable you choose
})
Set the instance id (recommended)
The instanceId
is used to identify the worker instance of your app that is connected to Inngest. This allows Inngest to support multiple instances (workers) of your app connected to Inngest.
By default, Inngest will attempt to use the hostname of the worker as the instance id. If you're running your app in a containerized environment, you can set the instanceId
to the container id.
// Set the instance ID to any environment variable that is unique to the worker
await connect({
apps: [...],
instanceId: process.env.MY_CONTAINER_ID,
})
Set the max concurrency (recommended)
The maxConcurrency
option is used to limit the number of concurrent steps that can be executed by the worker instance. This allows Inngest to distribute load across multiple workers and not overload a single worker.
The maxConcurrency
option is not yet supported. It will be supported in a future release before general availability.
await connect({
apps: [...],
maxConcurrency: 100,
})
Lifecycle
As a connect worker is a long-running process, it's important to understand the lifecycle of the worker and how it relates to the deployment of a new version of your app. Here is an overview of the lifecycle of a connect worker and where you can hook into it to handle graceful shutdowns and other lifecycle events.
CONNECTING
- The worker is establishing a connection to Inngest. This starts when connect()
is called.
First, the worker sends a request to the Inngest API via HTTP to get connection information. The response includes the WebSocket gateway URL. The worker then connects to the WebSocket gateway.
ACTIVE
- The worker is connected to Inngest and ready to execute functions.
- The new
appVersion
is synced including the latest function configurations. - The worker begins sending and receiving "heartbeat" messages to Inngest to ensure the connection is still active.
- The worker will automatically reconnect if the connection is lost.
TypeScript
// The connect promise will resolve when the connection is ACTIVE
const connection = await connect({
apps: [...],
})
console.log(`The worker connection is: ${connection.state}`)
// The worker connection is: ACTIVE
RECONNECTING
- The worker is reconnecting to Inngest after a connection was lost.
The worker will automatically flush any in-flight steps via the HTTP API when the WebSocket connection is lost.
By default, the worker will attempt to reconnect to Inngest an infinite number of times. See the developer preview limitations for more details.
CLOSING
- The worker is beginning the shutdown process.
- New steps will not be accepted after this state is entered.
- Existing steps will be allowed to complete. The worker will flush any in-flight steps via the HTTP API after the WebSocket connection is closed.
By default, the SDK listens for SIGTERM
and SIGINT
signals and begins the shutdown process. You can customize this behavior by in each SDK:
// You can explicitly configure which signals the SDK should
// listen for by an array of signals to `handleShutdownSignals`:
const connection = await connect({
apps: [...],
// ex. Only listen for SIGTERM, or pass an empty array to listen to no signals
handleShutdownSignals: ['SIGTERM'],
})
You can manually close the connection with the close
method on the connection object:
await connection.close()
// Connection is now closed
CLOSED
- The worker's WebSocket connection has closed.
By this stage, all in-flight steps will be flushed via the HTTP API as the WebSocket connection is closed, ensuring that no in-progress steps are lost.
TypeScript
// The `closed` promise will resolve when the connection is "CLOSED"
await connection.closed
// Connection is now closed
WebSocket connection and HTTP fallback - While a WebSocket connection is open, the worker will receive and send all step results via the WebSocket connection. When the connection closes, the worker will fallback to the HTTP API to send any remaining step results.
Worker observability
In the Inngest Cloud dashboard, you can view the connection status of each of your workers. At a glance, you can see each worker's instance id, connection status, connected at timestamp, last heartbeat, the app version, and app version.
This view is helpful for debugging connection issues or verifying rolling deploys of new app versions.
Health checks
If you are running your app in a containerized environment, we recommend using a health check to ensure that your app is running and ready to accept connections. This is key for graceful rollouts of new app versions. If you are using Kubernetes, we recommend using the readinessProbe
to check that the app is ready to accept connections.
The simplest way to implement a health check is to create an http endpoint that listens for health check requests. As connect is an outbound WebSocket connection, you'll need to create a small http server that listens for health check requests and returns a 200 status code when the connection to Inngest is active.
Here is an example of using connect
with a basic Node.js http server to listen for health check requests and return a 200 status code when the connection to Inngest is active.
import { createServer } from 'http';
import { connect } from 'inngest/connect';
import { inngest, functions } from './src/inngest';
(async () => {
const connection = await connect({
apps: [{ client: inngest, functions }]
});
console.log('Worker: connected', connection);
// This is a basic web server that only listens for the /ready endpoint
// and returns a 200 status code when the connection to Inngest is active.
const httpServer = createServer((req, res) => {
if (req.url === '/ready') {
if (connection.state === ConnectionState.ACTIVE) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('OK');
} else {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('NOT OK');
}
return;
}
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('NOT FOUND');
});
// Start the server on a port of your choice
httpServer.listen(8080, () => {
console.log('Worker: HTTP server listening on port 8080');
});
// When the Inngest connection has gracefully closed,
// this will resolve and the app will exit.
await connection.closed;
console.log('Worker: Shut down');
httpServer.close();
})();
Kubernetes readiness probe
If you are running your app in Kubernetes, you can use the readinessProbe
to check that the app is ready to accept connections. For the above example running on port 8080, the readiness probe would look like this:
readinessProbe:
httpGet:
path: /ready
initialDelaySeconds: 3
periodSeconds: 10
successThreshold: 3
failureThreshold: 3
Self hosted Inngest
Self-hosting support for connect
is in development. Please contact us for more info.
If you are self-hosting Inngest, you need to ensure that the Inngest WebSocket gateway is accessible within your network. The Inngest WebSocket gateway is available at port 8289
.
Depending on your network configuration, you may need to dynamically re-write the gateway URL that the SDK uses to connect.
const connection = await connect({
apps: [...],
rewriteGatewayEndpoint: (url) => { // ex. "wss://gw2.connect.inngest.com/v0/connect"
// If not running in dev mode, return
if (!process.env.INNGEST_DEV) {
const clusterUrl = new URL(url);
clusterUrl.host = 'my-cluster-host:8289';
return clusterUrl.toString();
}
return url;
},
})
Migrating from serve
Guide on migration from serve
to connect
coming soon
Developer preview
The connect
API is currently in developer preview. This means that the API is not yet recommended for critical production workloads and is subject to breaking changes.
During the developer preview, the connect
API is available to all Inngest accounts with the following plan-limits:
- Free plan: 2 concurrent worker connections
- All paid plans: 10 concurrent worker connections
- Max apps per connection: 10
Final plan limitations will be announced prior to general availability. Please contact us if you need to increase these limits.
Limitations
During the developer preview, there are some limitations to using connect
to be aware of. Please contact us if you'd like clarity on any of the following:
- Lost connections may result in long timeouts before retries - If a connection is lost in the middle of a step, the step may result in a timeout of the max step duration (2 hours) before the step is retried. Graceful shutdowns, as documented above, handle this correctly, but if a networking issue occurs and the worker cannot re-establish connection, the step may result in a timeout.
- Worker-level maximum concurrency - This is not yet supported. When completed, each worker can configure the maximum number of concurrent steps it can handle. This allows Inngest to distribute load across multiple workers and not overload a single worker.
- Reconnection policy is not configurable - The SDK will attempt to reconnect to Inngest an infinite number of times. We will expose a configurable reconnection policy in the future.
- Rollbacks - Rollbacks of app versions may not work as expected. Additional functionality and control around rollbacks is coming in a future release.