Every Koa Feature Is an async Function Registered With app.use
Middleware Introduction
Koa middleware are async functions that receive ctx and next. Learn how to write them, register them with app.use, and understand the execution stack.
What you'll learn
- Write a Koa middleware function with the correct async (ctx, next) signature
- Register middleware with app.use and understand registration order
- Know when to call await next() and when to skip it
In Koa, everything is middleware. There is no built-in routing layer, no
automatic body parsing, and no bundled session support. Each capability is a
function you register with app.use, and Koa calls them in order for every
incoming request.
The Middleware Signature
A Koa middleware function is an async function that accepts two arguments:
async function myMiddleware(ctx, next) {
// 1. Code here runs before the rest of the stack
await next();
// 2. Code here runs after the rest of the stack has finished
}
app.use(myMiddleware); ctx— the context object (request + response + helpers).next— a function that, when awaited, passes control to the next middleware in the stack.
Registering Middleware
app.use() appends functions to the middleware stack in the order you call it:
import Koa from "koa";
const app = new Koa();
app.use(async (ctx, next) => {
console.log("Middleware A — before");
await next();
console.log("Middleware A — after");
});
app.use(async (ctx, next) => {
console.log("Middleware B — before");
await next();
console.log("Middleware B — after");
});
app.use(async (ctx) => {
ctx.body = "Hello!";
console.log("Middleware C — response set");
});
app.listen(3000); For a single request, the console output is:
Middleware A — before
Middleware B — before
Middleware C — response set
Middleware B — after
Middleware A — after
Skipping next()
If you do not call await next(), the middleware stack stops there. This
is useful for short-circuiting a request, such as returning a cached response
or rejecting an unauthenticated request:
app.use(async (ctx, next) => {
if (!ctx.headers["x-api-key"]) {
ctx.status = 401;
ctx.body = { error: "Unauthorized" };
return; // do not call next()
}
await next();
}); Up Next
See how calling await next() creates Koa’s signature “onion model” of
cascading middleware.