ServerMiddleware & Lifecycle
Architecture
Execution order, HandlerContext, and observability patterns.
Execution Order
Middleware is attached in routes/index.ts with a fixed order:
Order
- sessionMiddleware — Resolve user session from cookies/headers
- tenantMiddleware — Resolve org and attach TenantPrisma
- requireAuth — Ensure authenticated requests
- lifecycleMiddleware — Run before/after lifecycle hooks
HandlerContext
Middleware composes the HandlerContext used by services:
interface HandlerContext {
// Request
requestId: string;
path: string;
method: string;
// Auth
user: User | null;
session: Session | null;
// Tenant
org: string;
prisma: TenantPrisma;
}Context Access in Handlers
app.get("/api/resource", requireAuth, async (c) => {
const { user, org, prisma } = c.get("context");
// Use context for DB operations
});Observability
- Add structured logs with
requestId,org,userId - Include timing metadata
- Log before throwing errors
Safety
- Fail-fast: Throw HTTP errors immediately to prevent partial state
- Avoid sync work: Move expensive operations to background
- Idempotent: Ensure middleware can run multiple times safely