inngest-middleware
This skill teaches how to implement middleware in Inngest durable functions to handle cross-cutting concerns like structured logging, error tracking…
Identity proven by GitHub's verified organisation badge (inngest)
- Agents
- Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode, claude.ai and API
- License
- Apache-2.0 (permissive)
- Pin
- 082798apinned Oct 9, 2026
- Context cost
- about 2,400 tokenswhen the skill loads
- GitHub stars
- 28on inngest/inngest-skills
- Scripts
- None found
What it does
“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 apply uniformly across many functions. Covers Inngest middleware lifecycle, creating custom middleware, dependencyInjectionMiddleware, @inngest/middleware-encryption, @inngest/middleware-sentry, and custom middleware patterns.”
Generated summary from the skill's own text
This skill teaches how to implement middleware in Inngest durable functions to handle cross-cutting concerns like structured logging, error tracking, dependency injection, and data encryption. Middleware runs at key lifecycle points across all or specific functions, enabling observability, telemetry, and shared client access patterns.
When to use it
- Adding logging, tracing, or metrics across multiple functions
- Injecting database or API clients into function handlers
- Encrypting sensitive data in function payloads and outputs
- Tracking errors and exceptions with external services like Sentry
When not to
- Building realtime features in Inngest v4, use inngest-realtime instead
- Working with Python or Go, refer to language-specific Inngest documentation
Install
These commands install from the publisher's repository and need no account.
skills CLI
npx skills add inngest/inngest-skills --skill inngest-middlewareInstalls from the repository's default branch, which may have changed since the commit we checked.
GitHub CLI 2.90 or later
gh skill install inngest/inngest-skills inngest-middleware@082798a627bbe9c3ed3a6638a9f56116a035f122Installs the commit we checked (082798a).
Copy by hand
Download the folder at 082798a and put it in .claude/skills/inngest-middleware for Claude Code and in .agents/skills/inngest-middleware for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.
Copy for your agent
A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.
Prompt
Install the agent skill "inngest-middleware" by Inngest. Source, pinned to commit 082798a627bbe9c3ed3a6638a9f56116a035f122: https://github.com/inngest/inngest-skills/tree/082798a627bbe9c3ed3a6638a9f56116a035f122/skills/inngest-middleware 1. Download that folder at exactly this commit. Do not use the default branch. 2. Copy every file unchanged, keeping the folder structure, into .claude/skills/inngest-middleware/ for Claude Code and .agents/skills/inngest-middleware/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist. 3. Do not edit the files, and do not run any script in the folder unless I ask you to. 4. When you are done, list the files you copied and where you put them. Listing and checks: https://www.agentnative.dev/skills/inngest/inngest-middleware-inngest-skills
SKILL.md at the pin
---
name: inngest-middleware
description: 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 apply uniformly across many functions. Covers Inngest middleware lifecycle, creating custom middleware, dependencyInjectionMiddleware, @inngest/middleware-encryption, @inngest/middleware-sentry, and custom middleware patterns.
---
# 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
```typescript
const inngest = new Inngest({
id: "my-app",
middleware: [
loggingMiddleware, // Runs 1st
errorMiddleware // Runs 2nd
]
});
inngest.createFunction(
{
id: "example",
middleware: [
authMiddleware, // Runs 3rd
metricsMiddleware // Runs 4th
],
triggers: [{ event: "test" }]
},
async () => {
/* function code */
}
);
```
**Order matters:** Client middleware runs first, then function middleware, in the order specified.
## Creating Custom Middleware
### Basic Middleware Structure
```typescript
import { InngestMiddleware } from "inngest";
const loggingMiddleware = new InngestMiddleware({
name: "Logging Middleware",
init() {
// Setup phase - runs when client initializes
const logger = setupLogger();
return {
// Function execution lifecycle
// Note: `fn` is loosely typed in middleware generics; fn.id works at runtime
onFunctionRun({ ctx, fn }) {
return {
beforeExecution() {
logger.info("Function starting", {
functionId: fn.id,
eventName: ctx.event.name,
runId: ctx.runId
});
},
afterExecution() {
logger.info("Function completed", {
functionId: fn.id,
runId: ctx.runId
});
},
transformOutput({ result }) {
// Log function output
logger.debug("Function output", {
functionId: fn.id,
output: result.data
});
// Return unmodified result
return { result };
}
};
},
// Event sending lifecycle
onSendEvent() {
return {
transformInput({ payloads }) {
logger.info("Sending events", {
count: payloads.length,
events: payloads.map((p) => p.name)
});
// Spread to convert readonly array to mutable array
return { payloads: [...payloads] };
}
};
}
};
}
});
```
### Python Implementation
Python middleware follows a similar pattern. See [Dependency Injection Reference](./references/dependency-injection.md) for complete Python examples.
````
## Dependency Injection
Share expensive or stateful clients across all functions. **See [Dependency Injection Reference](./references/dependency-injection.md) for detailed patterns.**
### Quick Example - Built-in DI
```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 }
});
}
);
````
## Middleware Packages
Beyond `dependencyInjectionMiddleware` (built-in, shown above), Inngest provides official middleware as **separate packages**. **See [Middleware Reference](./references/built-in-middleware.md) for complete details.**
### Encryption Middleware
```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
})
]
});
```
Automatically encrypts all step data, function output, and event `data.encrypted` field. Supports key rotation via `fallbackDecryptionKeys`.
### Sentry Error Tracking
```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()]
});
```
Captures exceptions, adds tracing to each function run, and includes function ID and event names as context. Requires `@sentry/*@>=8.0.0`.
## Common Middleware Patterns
### Metrics and Performance Tracking
```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 };
}
};
}
};
}
});
```
### Advanced Patterns
**Authentication:** Validate tokens and inject user context
**Conditional logic:** Apply middleware based on event type or function
**Circuit breakers:** Prevent cascading failures from external services
### Configuration-Based Middleware
Create reusable middleware with configuration options for different environments and use cases. See reference documentation for complete examples.
## Best Practices
### Design Principles
1. **Keep middleware focused:** One concern per middleware
2. **Handle errors gracefully:** Don't let middleware crash functions
3. **Consider performance:** Middleware runs on every execution
4. **Use proper typing:** Let TypeScript infer middleware types
5. **Test thoroughly:** Middleware affects all functions that use it
### Common Use Cases to Implement
- **Retry logic** for transient failures
- **Circuit breakers** for external service calls
- **Request/response logging** for debugging
- **User context enrichment** from external sources
- **Feature flags** for gradual rollouts
- **Custom authentication** and authorization checks
### Error Handling in Middleware
```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)
From inngest/inngest-skills at 082798a, shown as plain text under its license: Apache-2.0 (permissive). The license text is in LICENSE.
View SKILL.md on GitHub at 082798aFiles
- SKILL.md10 KB · 7870d820b8c9
- references/
- built-in-middleware.md13 KB · ad445a368725
- dependency-injection.md10 KB · 089b5606051e
3 files, 33 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.
Skill folder on GitHub at 082798aAlso in
The same SKILL.md content appears in these places too. We list it once and credit the oldest public source.
More from Inngest
inngest-agent-evals
Builds production evaluation workflows for AI agents on Inngest using direct and deferred scoring, sessions for grouping related runs, step experiments for…
Claude Code, Codex, Cursor +4 · about 2.6K tokens · pinned 6 days ago
inngest-agents
Build durable AI agents and multi-step agentic workflows using Inngest and AgentKit.
Claude Code, Codex, Cursor +4 · about 2.1K tokens · pinned 6 days ago
inngest-api-cli
This skill routes the agent to use the Inngest CLI `inngest api` command for operational tasks like debugging runs, querying events, syncing apps, invoking…
Claude Code, Codex, Cursor +4 · about 1.9K tokens · pinned 6 days ago
inngest-api
This skill enables agents to interact with the Inngest REST API v2 for Cloud operations, raw HTTP requests, and API reference lookups.
Claude Code, Codex, Cursor +4 · about 1.1K tokens · pinned 6 days ago
inngest-brownfield-audit
This skill audits existing TypeScript or JavaScript codebases to identify where Inngest can improve reliability and durability.
Claude Code, Codex, Cursor +4 · about 2.5K tokens · pinned 6 days ago
inngest-cli
This skill enables installation and operation of the Inngest CLI for local development and testing with the Dev Server, which provides a browser UI at…
Claude Code, Codex, Cursor +4 · about 3.4K tokens · pinned 6 days ago
Related in Backend and APIs
inngest-events
This skill teaches event design and delivery patterns for Inngest, covering event payload structure, naming conventions, idempotency with event IDs, scheduled…
by InngestOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.9K tokens · pinned 6 days ago
inngest-flow-control
This skill provides Inngest flow control mechanisms to manage API rate limits, prevent duplicate processing, and ensure fair resource allocation.
by InngestOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.1K tokens · pinned 6 days ago
speech-engine
This skill integrates ElevenLabs Speech Engine to add real-time voice conversations to custom agent runtimes.
by ElevenLabsOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.4K tokens · pinned 6 days ago
airflow-plugins
Builds Airflow 3.1+ plugins that embed FastAPI apps, custom UI pages, React components, middleware, macros, and operator links directly into the Airflow UI…
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 5.8K tokens · pinned 6 days ago
authoring-go-sdk-tasks
Enables writing Airflow task logic in Go by implementing the Go SDK's native API.
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 2K tokens · pinned 6 days ago
authoring-java-sdk-tasks
This skill teaches how to write Airflow task logic in Java, Kotlin, or other JVM languages using the Airflow Java SDK.
by AstronomerOfficial publisher
Claude Code, Codex, Cursor +4 · about 2.4K tokens · pinned 6 days ago
Open roles at Inngest
No open roles at Inngest on the Agent Native jobs board right now.
Browse the jobs board