inngest-middleware
Use when adding cross-cutting concerns to durable functions — structured logging or tracing across all functions, error tracking with Sentry, payload encryption for sensitive data, dependency injection of clients (DB, Stripe, etc.) into function handlers, custom telemetry, or behavior that should ap
By inngest · 3,300 installs
npx skills add inngest/inngest-skills --skill inngest-middleware
Source repository · Upstream listing
Inngest Middleware
Master Inngest middleware to handle cross cutting concerns like logging, error tracking, dependency injection, and data transformation. Middleware runs at key points in the function lifecycle, enabling powerful patterns for observability and shared functionality.
These skills are focused on TypeScript. For Python or Go, refer to the [Inngest documentation](https://www.inngest.com/llms.txt) for language specific guidance. Core concepts apply across all languages.
Note: The middleware system was significantly rewritten in v4. The lifecycle hooks documented here reflect the v4 API. If migrating from v3, consult the [migration guide](https://www.inngest.com/docs markdown/reference/typescript/v4/migrations/v3 to v4) for details on breaking changes.
⚠ For Realtime use the inngest realtime skill, NOT this one. Inngest v3 used realtimeMiddleware() from @inngest/realtime to inject a publish arg into function handlers. v4 ships realtime natively — step.realtime.publish is built in, no middleware required. Do NOT install @inngest/realtime on a v4 project (it's a v3 era package and produces TypeError: Cls is not a constructor at runtime). See the inngest realtime skill for the v4 pattern.
What is Middleware?
Middleware allows code to run at various points in an Inngest client's lifecycle during function execution, event sending, and more. Think of middleware as hooks into the Inngest execution pipeline.
When to use middleware:
Observability: Add logging, tracing, or metrics
Dependency injection: Share client instances across functions
Data transformation: Encrypt/decrypt, validate, or enrich data
Error handling: Custom error tracking and alerting
Authentication: Validate user context or permissions
Middleware Lifecycle
Middleware can be registered at client level (affects all functions) or function level (affects specific functions).
Execution Order
Order matters: Client middleware runs first, then function middleware, in the order specified.
Creating Custom Middleware
Basic Middleware Structure
Python Implementation
Python middleware follows a similar pattern. See [Dependency Injection Reference](./references/dependency injection.md) for complete Python examples.
typescript
import { dependencyInjectionMiddleware } from "inngest";
const inngest = new Inngest({
id: 'my app',
middleware: [
dependencyInjectionMiddleware({
openai: new OpenAI(),
db: new PrismaClient(),
}),
],
});
// Functions automatically get injected dependencies
inngest.createFunction(
{ id: "ai summary", triggers: [{ event: "document/uploaded" }] },
async ({ event, openai, db }) = {
// Dependencies available in function context
const summary = await openai.chat.completions.create({
messages: [{ role: "user", content: event.data.content }],
model: "gpt 4",
});
await db.document.update({
where: { id: event.data.documentId },
data: { summary: summary.choices[0].message.content }
});
}
);
bash
npm install @inngest/middleware encryption
typescript
import { encryptionMiddleware } from "@inngest/middleware encryption";
const inngest = new Inngest({
id: "my app",
middleware: [
encryptionMiddleware({
key: process.env.ENCRYPTION KEY
})
]
});
bash
npm install @inngest/middleware sentry
typescript
import as Sentry from "@sentry/node";
import { sentryMiddleware } from "@inngest/middleware sentry";
Sentry.init({
/ your Sentry config /
});
const inngest = new Inngest({
id: "my app",
middleware: [sentryMiddleware()]
});
typescript
const metricsMiddleware = new InngestMiddleware({
name: "Metrics Tracking",
init() {
return {
onFunctionRun({ ctx, fn }) {
let startTime: number;
return {
beforeExecution() {
startTime = Date.now();
metrics.increment("inngest.step.started", {
function: fn.id,
event: ctx.event.name
});
},
afterExecution() {
const duration = Date.now() startTime;
metrics.histogram("inngest.step.duration", duration, {
function: fn.id,
event: ctx.event.name
});
},
transformOutput({ result }) {
const status = result.error ? "error" : "success";
metrics.increment("inngest.step.completed", {
function: fn.id,
status: status
});
return { result };
}
};
}
};
}
});
typescript
const robustMiddleware = new InngestMiddleware({
name: "Robust Middleware",
init() {
return {
onFunctionRun({ ctx, fn }) {
return {
transformOutput({ result }) {
try {
// Your middleware logic here
return performTransformation(result);
} catch (middlewareError) {
// Log error but don't break the function
console.error("Middleware error:", middlewareError);
// Return original result on middleware failure
return { result };
}
}
};
}
};
}
});
Testing Middleware
Use Inngest's testing utilities ( createMockContext , createMockFunction ) to unit test middleware behavior.
For complete implementation examples and advanced patterns, see:
[Dependency Injection Reference](./references/dependency injection.md)
[Built in Middleware Reference](./references/built in middleware.md)