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:
- Middleware registered on the client, in descending order
- 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.
- Name
- ctx
- Type
- object
- Required
- optional
- Description
- The input data for the function. Only - eventand- runIdare 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
- input
- 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- ctxobject, including- steptooling.
 
- 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
- output
- 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() or step.sendEvent().
- Name
- input
- 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
- output
- 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() {
            // ...
          },
        };
      },
    };
  },
});