Middleware lifecycle
v2.0.0+

Registering and order

Middleware can be registered with Inngest clients or functions by providing an array of middleware.

// Adding middleware to a client
const inngest = new Inngest({
  id: "my-app",
  middleware: [errorHandlerMiddleware, loggingMiddleware],
});

// Adding middleware to a function
inngest.createFunction(
  { id: "example", middleware: [dbConnectionMiddleware] },
  { event: "test" },
  async () => {
    // ...
  }
);

Adding middleware contributes to an overall "stack" of middleware. If you register multiple middlewares, the SDK will group and run hooks for each middleware in the following order:

  1. Middleware registered on the client, in descending order
  2. Middleware registered on the function, in descending order

For example:

const inngest = new Inngest({
  id: "my-app",
  middleware: [
    logMiddleware, // This is executed first
    errorMiddleware, // This is executed second
  ],
});

inngest.createFunction(
  {
    id: "example",
    middleware: [
      dbSetupMiddleware, // This is executed third
      datadogMiddleware, // This is executed fourth
    ],
  },
  { event: "test" },
  async () => {
    // ...
  }
);

Hook reference

The init() function can return functions for two separate lifecycles to hook into.

💡 All lifecycle and hook functions can be synchronous or async functions - the SDK will always wait until a middleware's function has resolved before continuing to the next one.

onFunctionRun lifecycle

Triggered when a function is going to be executed.

Arguments
  • Name
    ctx
    Type
    object
    Required
    optional
    Description

    The input data for the function. Only event and runId are available at this point.

  • Name
    steps
    Type
    array
    Required
    optional
    Description

    An array of previously-completed step objects.

  • Name
    fn
    Type
    InngestFunction
    Required
    optional
    Description

    The function that is about to be executed.

  • Name
    reqArgs
    Type
    array
    Required
    optional
    Version
    v3.9.0+
    Description

    Arguments passed to the framework's request handler, which are used by the SDK's serve handler.

Returns
  • Name
    transformInput
    Type
    function
    Required
    optional
    Description

    Called once the input for the function has been set up. This is where you can modify the input before the function starts.

    Has the same input as the containing onFunctionRun() lifecycle function, but with a complete ctx object, including step tooling.

  • Name
    beforeMemoization
    Type
    function
    Required
    optional
    Description

    Called before the function starts to memoize state (running over previously-seen code).

  • Name
    afterMemoization
    Type
    function
    Required
    optional
    Description

    Called after the function has finished memoizing state (running over previously-seen code).

  • Name
    beforeExecution
    Type
    function
    Required
    optional
    Description

    Called before the function starts to execute (running code seen for the first time).

  • Name
    afterExecution
    Type
    function
    Required
    optional
    Description

    Called after the function has finished executing.

  • Name
    transformOutput
    Type
    function
    Required
    optional
    Description

    Called after the function has finished executing and before the response is sent back to Inngest. This is where you can modify the output.

  • Name
    beforeResponse
    Type
    function
    Required
    optional
    Description

    Called after the output has been set and before the response has been sent back to Inngest. Use this to perform any final actions before the request closes.

const myMiddleware = new InngestMiddleware({
  name: "My Middleware",
  init({ client, fn }) {
    return {
      onFunctionRun({ ctx, fn, steps }) {
        return {
          transformInput({ ctx, fn, steps }) {
            // ...
            return {
              // All returns are optional
              ctx: { /* extend fn input */ },
              steps: steps.map(({ data }) => { /* transform step data */ })
            }
          },
          beforeMemoization() {
            // ...
          },
          afterMemoization() {
            // ...
          },
          beforeExecution() {
            // ...
          },
          afterExecution() {
            // ...
          },
          transformOutput({ result, step }) {
            // ...
            return {
              // All returns are optional
              result: {
                // Transform data before it goes back to Inngest
                data: transformData(result.data)
              }
            }
          },
          beforeResponse() {
            // ...
          },
        };
      },
    };
  },
});

onSendEvent lifecycle

Triggered when an event is going to be sent via inngest.send(), step.sendEvent(), or step.invoke().

Output
  • Name
    transformInput
    Type
    function
    Required
    optional
    Description

    Called before the events are sent to Inngest. This is where you can modify the events before they're sent.

  • Name
    transformOutput
    Type
    function
    Required
    optional
    Description

    Called after events are sent to Inngest. This is where you can perform any final actions and modify the output from inngest.send().

const myMiddleware = new InngestMiddleware({
  name: "My Middleware",
  init: ({ client, fn }) => {
    return {
      onSendEvent() {
        return {
          transformInput({ payloads }) {
            // ...
          },
          transformOutput() {
            // ...
          },
        };
      },
    };
  },
});