Request lifecycle
Understanding the request lifecycle helps when debugging complex modules. Every HTTP request—page or API—follows the same high-level flow:
- Routing – Next.js dispatches the request to a generated route handler. For APIs this lives in
src/app/api/[...slug]/route.ts. The handler locates the module definition (method + path) and loads its module file. - Container scope – A new Awilix scope is created by
createRequestContainer. Core services (logger, repositories, RBAC, query engine, data engine) are registered, then module registrars extend the container. - Auth context – The framework resolves session/tenant data, attaches it to the request context, and enforces
requireAuth/requireFeaturesmetadata declared by the route or page. - Business logic – Handler code (often the CRUD factory) executes, relying on injected services. Writes go through MikroORM repositories or the data engine; reads use the query engine for projection and filtering.
- Events – If the handler calls
eventBus.emitEvent, subscribers are resolved lazily and executed. Persistent subscribers are queued when offline and retried later. - Response & telemetry – The handler returns JSON/NextResponse. Middleware logs timing and errors with correlation identifiers for tracing across services.
The same lifecycle powers server actions and background jobs; in each case we create a scope, load module registrars, and execute the requested operation in a tenant-aware context.