Skip to content

Configuration and environment variables

AddInngest takes a delegate that sets InngestOptions. Anything left unset is read from configuration, so the environment variables Inngest’s other SDKs use work here too. Options set in code win.

builder.Services.AddInngest(options =>
{
options.AppId = "shop";
options.AppVersion = "2026.10.3";
});

AppId is the only required setting. The SDK checks it when the host starts.

Option Variable Default
AppId required
AppVersion none
IsDev, DevServerUrl INNGEST_DEV cloud mode; the dev server at http://localhost:8288
EventKey INNGEST_EVENT_KEY none; not needed in dev mode
SigningKey INNGEST_SIGNING_KEY none; required in cloud mode
SigningKeyFallback INNGEST_SIGNING_KEY_FALLBACK none
Environment INNGEST_ENV the signing key’s environment
BaseUrl INNGEST_BASE_URL
ApiBaseUrl INNGEST_API_BASE_URL https://api.inngest.com
EventApiBaseUrl INNGEST_EVENT_API_BASE_URL https://inn.gs
ServeOrigin INNGEST_SERVE_ORIGIN the origin the request arrived on
ServePath INNGEST_SERVE_PATH the path the request arrived on
AllowInBandSync INNGEST_ALLOW_IN_BAND_SYNC true
AllowUnsignedSync INNGEST_ENABLE_UNAUTHED_SYNC true
Streaming INNGEST_STREAMING false
SessionPropagation INNGEST_SESSION_PROPAGATION true
SerializerOptions JsonSerializerDefaults.Web

An address in a variable may leave out the scheme, as in INNGEST_DEV=localhost:8288. The dev server, localhost, IP addresses, names without dots (such as a container’s) and names ending in .internal, .local or another private suffix get http. Any other host gets https, so a key never crosses the internet in clear text by mistake.

The SDK reads the variables through IConfiguration when the host has one, so they can also come from appsettings.json, user secrets, Azure App Configuration or any other configuration source, under the same names:

appsettings.Development.json
{
"INNGEST_DEV": "1"
}

Without IConfiguration, for example in a plain ServiceCollection, it reads the process environment.

AddInngest can also read the options from a configuration section, so that they sit in appsettings.json with the rest of the app’s settings:

appsettings.json
{
"Inngest": {
"AppId": "billing",
"EventKey": "...",
"SigningKey": "..."
}
}
builder.Services.AddInngest(builder.Configuration.GetSection("Inngest"));

Every option in the table above has a key of the same name, except SerializerOptions. Checkpointing is a subsection with the keys Enabled, MaxRuntime, BufferedSteps and MaxInterval. A duration is an Inngest time string such as 30s, 5m or 1h30m, or the form .NET writes a TimeSpan in, such as 00:00:30. Keys the SDK does not know are ignored. A value it cannot read stops the app with an error that names the key, such as Inngest:IsDev must be true or false, but it is 'maybe'.

The section is the lowest layer. A setting comes from the first of these that has it:

  1. Options set in code, in the callback of AddInngest or in Configure<InngestOptions>.
  2. The INNGEST_* variables.
  3. The section.
  4. The default.

So a container can still set INNGEST_DEV or INNGEST_SIGNING_KEY to override the file, and AddInngest and Configure<InngestOptions> can be called in any order. AppId may come from the section too; the startup check accepts it from either place.

The SDK reads the keys one by one instead of binding the section to InngestOptions, so this works in trimmed and Native AOT apps. Keep the keys out of the file you commit: user secrets, or environment variables such as Inngest__SigningKey, reach the section like any other configuration source.

The SDK runs in one of two modes:

  • Cloud mode is the default. Requests from Inngest must be signed with the signing key, and the SDK signs its answers. Events go to Inngest Cloud with the event key. Use it in every deployed environment.
  • Dev mode talks to a local dev server, checks no signatures and needs no keys.

INNGEST_DEV selects the mode: 1, true, on or yes for dev mode, 0, false, off or no for cloud mode, or the dev server’s URL, which also means dev mode. IsDev in code overrides it, and DevServerUrl sets the dev server’s address. A value the SDK cannot read stops the app with an error rather than silently falling back to cloud mode.

The event key lets the app send events; the signing key authenticates the traffic between Inngest and the app. Both come from the Inngest dashboard and belong in a secret store, not in source control. In cloud mode, an app without a signing key answers every request from Inngest with an error, and the Connect worker refuses to start.

Inngest’s event API takes the event key in the URL path, as in https://inn.gs/e/<key>. The SDK’s HttpClient logs no URLs for that reason, but HttpClient tracing records the full URL as url.full. If the app exports HttpClient spans, filter or redact them for the event API.

To rotate the signing key without downtime, deploy the new key as INNGEST_SIGNING_KEY and the old one as INNGEST_SIGNING_KEY_FALLBACK, promote the new key in Inngest, then remove the fallback. The SDK accepts signatures from either key while both are set, and retries API calls with the fallback when the current key is refused. Inngest describes the procedure in rotating keys.

Environment selects an Inngest branch environment, such as a preview deployment. When neither the option nor INNGEST_ENV is set, the SDK uses the branch name that common hosting platforms expose, from the first of BRANCH_NAME, VERCEL_GIT_COMMIT_REF, BRANCH, CF_PAGES_BRANCH, RENDER_GIT_BRANCH and RAILWAY_GIT_BRANCH that is set.

When Inngest syncs the app, the SDK reports the URL Inngest should call, built from the request it received. Behind a reverse proxy, a load balancer or a container platform, that may be an internal address. Set the public origin, and the path if the proxy rewrites it:

options.ServeOrigin = new Uri("https://shop.example.com");
options.ServePath = "/api/inngest";

INNGEST_SERVE_HOST, the old name of INNGEST_SERVE_ORIGIN, is read too.

Proxies and load balancers also close a connection that stays idle too long, often after 60 seconds, and that cuts off a long call: a step that runs for minutes, or a long function without steps. With streaming on, a call still running after three seconds is answered at once with a 201, then with a space every three seconds, then with its result, which Inngest reads from the stream:

options.Streaming = true;

INNGEST_STREAMING=true does the same, as it does for the TypeScript SDK. A call that ends within three seconds is answered as usual. Connect workers need no streaming: their connection to Inngest stays open.

A sync tells Inngest which functions the app has. Inngest starts one by sending a PUT to the endpoint:

  • In an in-band sync, the request is signed and the SDK answers with its configuration directly. This is the default when Inngest asks for it. AllowInBandSync = false forces the out-of-band kind.
  • In an out-of-band sync, the SDK posts its configuration to Inngest’s API, authenticated with the signing key. A deploy script can start one with an unsigned PUT, such as curl -X PUT https://shop.example.com/api/inngest. The SDK only ever sends its configuration to the Inngest it is configured for, but without ServeOrigin the URL in it comes from the request’s Host header, which an unsigned caller can set to any host. In production, set ServeOrigin (or INNGEST_SERVE_ORIGIN) or limit AllowedHosts; the SDK logs a warning when an unsigned sync takes the URL from the request. AllowUnsignedSync = false turns unsigned syncs off in cloud mode.

See apps and syncs in the Inngest docs.

BaseUrl points both the API and the event API at one address, such as a self-hosted Inngest server. ApiBaseUrl and EventApiBaseUrl set them separately. In dev mode they default to the dev server.

SerializerOptions is used for everything the SDK serializes on the app’s behalf: event data, step results, invoke payloads and function output. It defaults to JsonSerializerDefaults.Web. Add converters or naming policies there:

options.SerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());

The SDK takes a copy when it starts, so later changes have no effect. For trimmed or Native AOT apps, see Native AOT and trimming.

The Connect worker has settings of its own in ConnectOptions, with INNGEST_CONNECT_MAX_WORKER_CONCURRENCY and INNGEST_CONNECT_GATEWAY_URL as fallbacks.

inngest-dotnet is a community Inngest SDK for .NET. It is not affiliated with or endorsed by Inngest Inc.