Koa & Polka
Understand Koa and Polka as lightweight Node HTTP frameworks you may encounter in legacy codebases or minimal deployments.
Recipe
Quick-reference for recognizing each framework.
Koa (async context):
import Koa from "koa";
const app = new Koa();
app.use(async (ctx, next) => {
const start = Date.now();
await next();
ctx.set("X-Response-Time", `${Date.now() - start}ms`);
});
app.use(async (ctx) => {
ctx.body = { ok: true };
});
app.listen(3000);Polka (minimal router):
import polka from "polka";
const app = polka();
app.get("/users", (_req, res) => {
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify([{ id: 1 }]));
});
app.listen(3000);When to reach for this: Maintaining legacy Koa apps, or when you need the absolute smallest HTTP router (Polka).
Working Example
Side-by-side comparison of the same endpoint:
// --- Koa ---
import Koa from "koa";
import Router from "@koa/router";
import bodyParser from "koa-bodyparser";
const koaApp = new Koa();
const router = new Router({ prefix: "/api" });
koaApp.use(bodyParser());
router.get("/users/:id", async (ctx) => {
ctx.body = { id: ctx.params.id, name: "Ada" };
});
koaApp.use(router.routes());
// --- Polka ---
import polka from "polka";
import { json } from "body-parser";
const polkaApp = polka();
polkaApp.use(json());
polkaApp.get("/api/users/:id", (req, res) => {
const id = (req as { params: { id: string } }).params.id;
res.end(JSON.stringify({ id, name: "Ada" }));
});
// --- Modern equivalent: Hono ---
import { Hono } from "hono";
const honoApp = new Hono();
honoApp.get("/api/users/:id", (c) => c.json({ id: c.req.param("id"), name: "Ada" }));What this demonstrates:
- Koa uses
ctx(context) instead of(req, res) - Koa middleware is async-first (no
next()callback) - Polka is a minimal router on raw Node HTTP
- Hono provides a modern alternative with similar footprint
Deep Dive
Framework Comparison
| Factor | Koa | Polka | Hono | Express 5 |
|---|---|---|---|---|
| Size | Small | Tiny (~200 lines) | ~14KB | Medium |
| Middleware | Async ctx | Node (req, res) | Web Standard | (req, res, next) |
| Ecosystem | Mature but declining | Minimal | Growing fast | Largest |
| Edge support | No | No | Yes | No |
| Active maintenance | Maintained | Maintained | Very active | Active |
When You Still See Koa
- Older Node APIs built by teams who migrated from Express to Koa (~2015-2020)
- Projects using
@koa/router,koa-bodyparser,koa-jwt - Frameworks built on Koa (e.g., some GraphQL servers)
When You Still See Polka
- Microservices needing the smallest possible HTTP layer
- Bundled in tools like
sirv-cliand@sveltejs/kitadapter internals - Performance-sensitive internal services with < 5 routes
Gotchas
- Starting new projects on Koa - ecosystem is shrinking. Fix: use Hono or Fastify for new work.
- Koa without error middleware - async errors can be lost. Fix: use try/catch or
koa-error-handler. - Polka without body parser - POST bodies unreadable. Fix: add
body-parsermiddleware. - No built-in validation in either - manual or add Zod/Ajv. Fix: use Hono with
@hono/zod-validator. - Migrating Koa to Hono - similar middleware concepts but different API. Fix: rewrite routes; middleware patterns transfer.
- Assuming Polka has an ecosystem - it is a router only. Fix: bring your own middleware stack.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Hono | New lightweight project | Maintaining existing Koa app |
| Fastify 5 | Performance + schema validation | Absolute minimum size |
| Express 5 | Team familiarity | Edge deployment needed |
| Keep Koa | Existing stable codebase | Greenfield project |
FAQs
Should I migrate Koa to Hono?
When you need edge portability or active ecosystem growth. If Koa app is stable and low-churn, migration cost may not justify.
Is Koa dead?
Not dead, but declining. Maintained but fewer new projects. Express and Fastify dominate new Node APIs.
Why does Polka exist?
Luke Edwards built it as the smallest usable HTTP router. Useful when you need routing without framework overhead.
Can I use TypeScript with Koa?
Yes. @types/koa and @koa/router have type definitions. Less ergonomic than Hono's built-in types.
How does Koa compare to Express middleware?
Koa async middleware uses await next() (no callback). Errors propagate naturally in async chains. See Middleware Pattern.
Is Polka production-ready?
Yes for simple internal services. You bring all middleware, validation, and error handling yourself.
What is the migration path from Koa to Fastify?
Rewrite routes as Fastify plugins with JSON Schema. Koa ctx maps to Fastify req/reply. Plan a dedicated sprint.
Does NestJS support Koa?
No official Koa adapter. NestJS supports Express and Fastify only.
Related
- Hono Basics - modern lightweight alternative
- Middleware Pattern - middleware concepts
- Routing Without Frameworks - Polka-level minimalism
- Framework Selection Checklist - decision matrix
- Lightweight Frameworks Best Practices - section checklist
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.