# Roadmap

> What each release of the Inngest .NET SDK added, from the test host of the first preview to realtime, durable endpoints, webhooks and hosting on AWS Lambda and Azure Functions in 1.0.0, and what comes next.

Web page: https://damikun.github.io/inngest-dotnet/roadmap/

The SDK covers what most workflows need: steps, sleeps, waits for events, parallel steps and fan-out, invocations,
flow control, retries, middleware, realtime, request signing with key rotation, and Connect workers, on .NET 8 and
.NET 10 and under Native AOT. The packages are on [NuGet](https://www.nuget.org/packages/Inngest).

## New in 1.0.0

1.0.0 brings every package to its first major version, and adds 16 packages to the 5 that 0.1.0 had. From here on,
each package is checked against 1.0.0, so a change that would break code built against it fails the build. Durable
endpoints are the exception: they stay marked experimental and may still change.

- **A health check for apps that serve functions.** `AddInngest` on the health checks builder tells a readiness probe
  whether the app has its keys and Inngest answers a request that carries the signing key. It keeps the answer for 30
  seconds, and with `CheckSync` it also asks Inngest whether the app is synced. See
  [Health checks](https://damikun.github.io/inngest-dotnet/guides/deploying.md#health-checks).
- **AI calls as steps.** `AIWrapAsync` runs your own model call as a step that the Inngest UI shows with its input,
  and a rerun with an input edited there hands the handler the edited one. An input edited for `InferAsync` now
  reaches the request too.
- **Realtime.** Steps publish messages and stream text, such as a model's reply, once each; typed topics check what is
  published; `IInngestRealtime` publishes from anywhere, receives messages in .NET as an `IAsyncEnumerable` and mints
  tokens for the TypeScript SDK's `useRealtime`; and `MapInngestRealtime` relays messages to browsers as server-sent
  events, one subscription to Inngest for all the pages that watch a channel. See
  [Realtime](https://damikun.github.io/inngest-dotnet/guides/realtime.md).
- **Streaming.** `InngestOptions.Streaming`, or `INNGEST_STREAMING=true`, keeps a long call open behind proxies and
  load balancers that close idle connections. See [Behind a proxy](https://damikun.github.io/inngest-dotnet/guides/configuration.md#behind-a-proxy).
- **Sessions.** Events carry the sessions they belong to, a run's sessions are in `context.Sessions`, and what the run
  sends or invokes inherits them. See [Sessions](https://damikun.github.io/inngest-dotnet/guides/sending-events.md#sessions).
- **A test host for every step.** Mocks for waits for signals, sent signals, fetch and inference steps; AI wrap steps
  take run mocks; signals and realtime messages are recorded like events.
- **An Aspire integration.** `Inngest.Aspire.Hosting` runs the Inngest dev server, or a self-hosted server that signs its
  requests, as a container of an Aspire AppHost. It links the server's UI in the dashboard, syncs the apps of the
  AppHost and gives projects, containers and Connect workers the settings they need. See
  [Aspire](https://damikun.github.io/inngest-dotnet/guides/aspire.md).
- **A scope per step.** `RunScopedAsync` runs a step in a dependency injection scope of its own, created when the
  handler starts and disposed when it ends, so a `DbContext` is new for every step and attempt and nothing it tracks
  reaches the next one. The guide covers one `SaveChangesAsync` per step, transactions and execution strategies, and
  idempotency keys for steps that can run again. See [Scoped steps](https://damikun.github.io/inngest-dotnet/guides/scoped-steps.md).
- **Sentry and encryption packages.** `Inngest.Sentry` reports the errors of functions and steps to Sentry, tagged
  with the app, the function, the run and the event. `Inngest.Encryption` encrypts event data, step results and
  function output in the format of the TypeScript SDK's encryption middleware, so .NET and TypeScript services read
  each other's data. See [Middleware](https://damikun.github.io/inngest-dotnet/guides/middleware.md#encryption).
- **Durable endpoints.** An ASP.NET Core endpoint whose handler runs steps like a function. The caller gets the
  response directly, and Inngest takes the run over only when a step has to wait or fails. `UseInngestDurableEndpoints`
  and `WithDurableEndpoint`, or `[DurableEndpoint]` on a controller, set it up. Inngest calls the feature beta, so the
  .NET API is marked experimental and may change. See [Durable endpoints](https://damikun.github.io/inngest-dotnet/guides/durable-endpoints.md).
- **Tests against a real Inngest server.** `Inngest.Testing.Containers` is a Testcontainers module that runs the dev
  server, or a self-hosted server with signing and event keys, in Docker from your tests, points an app at it and has
  it sync the app, with the Connect gateway if you want one. `Inngest.Testing.Containers.AspNetCore` runs an ASP.NET Core
  app under `WebApplicationFactory` on a real port for it, on .NET 10. See
  [Testing with containers](https://damikun.github.io/inngest-dotnet/guides/testing-with-containers.md).
- **Chat clients as steps.** `Inngest.Extensions.AI` makes the model calls and the tool calls of a Microsoft.Extensions.AI
  `IChatClient` steps of the run, so a replay or a retry of a later step never calls the model or a tool twice. See
  [AI chat clients](https://damikun.github.io/inngest-dotnet/guides/ai.md).
- **A transactional outbox.** `Inngest.EntityFrameworkCore` saves events in the same Entity Framework Core transaction as
  your data, and a hosted dispatcher sends them afterwards, each under the id it got when it was added. See
  [Transactional outbox](https://damikun.github.io/inngest-dotnet/guides/outbox.md).
- **A source generator and analyzers.** A project that sets `InngestGenerateFunctionRegistration` gets
  `AddInngestFunctions()`, which registers its function classes without reflection, and an analyzer reports the types a
  Native AOT app has not listed in its `JsonSerializerContext`, with a code fix that adds them. Both come with the
  `Inngest` package. See [Source generator and analyzers](https://damikun.github.io/inngest-dotnet/guides/source-generator.md).
- **Templates and a dev server command.** `dotnet new inngest-web` and `dotnet new inngest-worker`, from the
  `Inngest.Templates` package, make a project with a typed event, a function and dev mode in its Development settings.
  `dotnet inngest dev`, from the `dotnet-inngest` tool, downloads the Inngest CLI, checks its SHA-256 and runs the dev
  server for the app, whose address it reads from the launch settings. See
  [Templates and tool](https://damikun.github.io/inngest-dotnet/guides/templates-and-tools.md).
- **Fan-out over a list.** `MapAsync` runs a step for each item of a list, with a limit on how many run at once, and
  returns the results in the order of the items. `ForEachAsync` does the same without results, `MapOutcomesAsync` runs
  every item and gives each its outcome, and `MapInChunksAsync` hands a list too long for one run to child runs in
  chunks. See [Fan-out over a list](https://damikun.github.io/inngest-dotnet/guides/fan-out.md).
- **Webhooks.** `Inngest.Webhooks` verifies the signatures of webhooks from Stripe, GitHub, Shopify, Standard Webhooks
  senders such as Clerk and Resend, and any HMAC. `MapInngestWebhook` sends each delivery as an event whose id is the
  delivery id, so a redelivery within 24 hours starts no second run. See [Webhooks](https://damikun.github.io/inngest-dotnet/guides/webhooks.md).
- **The user behind a run.** `Inngest.UserContext` carries selected claims of the signed-in user who sent an event into
  the runs it starts, protected with ASP.NET Core Data Protection, and a function reads them as `ICurrentUser` or
  `ClaimsPrincipal`. `Inngest.UserContext.AspNetCore` takes the user from `HttpContext.User`. See
  [User context](https://damikun.github.io/inngest-dotnet/guides/user-context.md).
- **AWS Lambda and Azure Functions.** `Inngest.AwsLambda` serves functions from a Lambda function behind API Gateway or
  a function URL with `InngestLambdaHandler`, also as a Native AOT executable. `Inngest.AzureFunctions` serves them
  from an HTTP-triggered function of the isolated worker with `ServeInngestAsync`. See
  [Running on AWS Lambda](https://damikun.github.io/inngest-dotnet/guides/aws-lambda.md) and
  [Azure Functions](https://damikun.github.io/inngest-dotnet/guides/azure-functions.md).
- **Realtime in Blazor and SignalR.** `Inngest.Blazor` shows realtime messages with `RealtimeView<TData>` in Blazor
  Server, WebAssembly and interactive Auto. `Inngest.SignalR` forwards them to the clients of a SignalR hub, with one
  subscription to Inngest shared by the clients of a channel. See [Realtime in Blazor](https://damikun.github.io/inngest-dotnet/guides/blazor.md)
  and [SignalR](https://damikun.github.io/inngest-dotnet/guides/signalr.md).
- **Docs for AI assistants.** Every page of this site has a Markdown copy, `llms.txt` lists them and `llms-full.txt`
  holds them all, so a coding assistant can read the docs as text. A guide lists the names that differ from the
  TypeScript SDK and the rules that keep a function correct when it replays. See
  [AI coding assistants](https://damikun.github.io/inngest-dotnet/guides/ai-assistants.md).

## New in 0.1.0

The first stable release of `Inngest`, `Inngest.AspNetCore`, `Inngest.Connect`, `Inngest.Testing` and
`Inngest.OpenTelemetry`, with the fixes of a second code review:

- Middleware that finishes async work after the call has answered no longer makes the SDK spin on the thread pool, and
  hooks can wait on the tasks a function started, as step handlers can.
- `off` and `no` in Inngest's environment variables, such as `INNGEST_DEV=off`, read as false.
- A call that finished answers even when disposing its services throws.
- Checkpointed steps and runs with deeply nested outputs read back.
- Batch timeouts are written in hours, which Inngest can parse.
- A Connect worker's instance id defaults to the full host name, as in the TypeScript SDK.

## New in 0.1.0-preview\.3

- **Fixes from a code review.** A step that awaits a task the function started before it no longer hangs the call,
  and a task the function started, such as one a singleton caches, completes even after the call has answered.
  Connect keeps flushing replies over HTTP whatever the HTTP client throws, and no longer gives up a lease Inngest
  has just renewed. Deeply nested step results read back, and the endpoint gets past an app's fallback
  authorization policy.
- **Safer defaults.** The event key stays out of the HttpClient logs, an address without a scheme gets `https`
  outside a private network, and an unsigned sync that takes its URL from the request logs a warning.
- **Every configuration problem at once.** The SDK checks every function at startup and lists all problems, each
  naming its function. It also refuses duplicate triggers, as Inngest does, and accepts a concurrency limit of 0,
  which means no limit.
- **Attributes of your own.** The trigger and flow control attributes derive from `FunctionOptionsAttribute`, so an
  app can write an attribute that bundles options several functions share.
- **Every step type in telemetry**, with names for signal, fetch and AI steps too.
- **A test host closer to Inngest.** A function's own middleware runs around mocked steps and recorded sends, the
  ids of one send sort in send order, and calls carry a job id.
- **Checked packages.** Each package is validated against the previous release, so a breaking API change fails the
  build, and the packages depend on exactly the Inngest of their own version.

## New in 0.1.0-preview\.2

- **Typed events.** An event's data record implements `IInngestEventData` and carries the event's name, so sends,
  triggers, waits and cancellations name the type instead of repeating a string.
- **Attributes on function classes.** `[InngestFunction]`, `[EventTrigger<T>]`, `[CronTrigger]`, `[Concurrency]`,
  `[CancelOn<T>]` and the other flow control attributes keep a function's id, triggers and limits on its class.
  `AddFunction<T>()` reads them, and options written in code work as before.
- **Typed results and invoke by class.** `InngestFunction<TEvent, TResult>` gives a function a result type, and
  `InvokeAsync<TFunction, TResult>` invokes it by its class, with the compiler checking the result.
- **Settings from `appsettings.json`.** `AddInngest(builder.Configuration.GetSection("Inngest"))` reads the
  `Inngest` section, and `INNGEST_*` variables still win over it. Like the attributes and typed events, it works
  under Native AOT.
- **The test host by class.** `RunAsync<TFunction>` runs a function by its class, and
  `StepMocks.Invoke<TFunction, TResult>` checks what a mocked invoke returns.

## New in 0.1.0-preview\.1

- **A test host, `Inngest.Testing`.** Unit-test a function the way Inngest runs it, call by call, with mocks for
  steps, sleeps, waits and invokes.
- **OpenTelemetry, `Inngest.OpenTelemetry`.** Traces for calls and steps, and metrics for runs, retries and
  durations, without writing the middleware yourself.
- **Connect health checks.** The worker's connection state and a health check for readiness probes.
- **Race mode for parallel steps.** A race resumes as soon as its first step finishes, for races such as approved
  or rejected.
- **A runs client.** Read a run's status and output, list the runs of an event, and cancel runs from your own code.
- **Signals, durable fetch and AI inference** as steps, and sending events or signals to another environment.
- **Checkpointing, opt-in.** Consecutive steps run in one request and are saved to Inngest in the background, with
  fewer requests per run.
- **Smaller additions.** Event access in middleware, middleware for one function, payload transforms, typed system
  events, the cause of a failed step, cron jitter and readable step names in the Inngest UI.

## Next

- **Guides** for versioning, idempotency, loops, expressions and local development.
- **Checkpointing on by default**, once it has more time against Inngest Cloud.
- **Durable endpoints out of experimental**, with resumes for endpoints that require authorization and support in
  the test host.
- **A validation middleware package**, built on the payload transforms.

## After that

- More Roslyn analyzers, and `defer`.

Ideas and pull requests are welcome on [GitHub](https://github.com/damikun/inngest-dotnet/issues).
