Skip to main content
Middleware is grammY’s mechanism for processing updates. Think of middleware as a chain of functions that handle incoming updates from Telegram.

What is Middleware?

In simple terms, middleware is just a fancy word for a listener. When you write:
The function you pass is middleware. It receives a Context object and processes it.

The Middleware Signature

Middleware functions have this signature:
Context
The context object containing the update and API methods
NextFunction
A function that invokes the next middleware in the chain

Example Middleware

The next Function

The next function is crucial to understanding middleware. It:
  1. Passes control to the next middleware in the chain
  2. Returns a Promise that resolves when downstream middleware completes
  3. Allows you to run code both before and after downstream middleware
Always await next() if you call it! Forgetting to await can lead to unexpected behavior and unhandled promise rejections.

Middleware Chain

Middleware executes in the order it’s registered:
If middleware doesn’t call next(), the chain stops:

Registering Middleware

bot.use() - Universal Middleware

Runs for all updates:

bot.on() - Filtered Middleware

Runs only for specific update types:
See Filter Queries for all available filters.

bot.command() - Command Middleware

bot.hears() - Text Matching

bot.callbackQuery() - Callback Query Handling

Other Specialized Methods

The Composer Class

The Bot class extends Composer, which provides all middleware registration methods. You can use Composer independently for modular code:

Advanced Middleware Patterns

Conditional Execution with filter()

Run middleware only when a custom condition is met:

Excluding Updates with drop()

Skip middleware for certain updates:

Branching with branch()

Choose between two middleware paths:

Routing with route()

Route to different handlers based on a value:

Lazy Middleware with lazy()

Generate middleware dynamically per update:

Concurrent Middleware with fork()

Run middleware concurrently to the main stack:

Error Boundaries

Catch errors in specific middleware subtrees:
See Error Handling for comprehensive error handling.

Middleware Objects

Middleware can be packaged as objects:
This is how plugins work internally.

Middleware Composition

You can chain middleware registration:
Each method returns a new Composer instance:

Running Middleware Manually

Run middleware with the run() function:

Best Practices

Order MattersRegister middleware in order of specificity:
Always Call next() or Stop the ChainEither call next() to continue, or handle the update completely:
Don’t Register Middleware Inside MiddlewareThis creates a memory leak:
grammY will throw an error if you try this after calling bot.start().
Use Composer for Modular Code

Middleware Flow Diagram

Type Safety

Middleware is fully typed:
With filter queries: