Request Lifecycle
Understanding Plumego’s request lifecycle is the key to understanding everything else.
Once you can answer:
“When a request arrives, what happens next — exactly, step by step?”
Most architectural and debugging questions become trivial.
This document describes the complete, deterministic lifecycle of a single request in Plumego.
The Lifecycle in One Sentence
In Plumego:
An incoming HTTP request is wrapped in a Context, passed through an explicit middleware chain, routed deterministically, handled exactly once, and then discarded.
There are no hidden phases.
High-Level Lifecycle Overview
At the highest level, the lifecycle looks like this:
HTTP Server
→ Plumego ServeHTTP
→ Context creation
→ Global middleware (before)
→ Route matching
→ Scoped middleware (before)
→ Handler
← Scoped middleware (after)
← Global middleware (after)
→ Response completed
→ Context discarded
Every step is explicit and predictable.
Step 1: HTTP Server Receives the Request
The lifecycle begins outside Plumego.
Go’s net/http.Server:
- Accepts a connection
- Parses the HTTP request
- Calls
ServeHTTP
Plumego does not participate in this phase.
This is intentional.
Step 2: Plumego Enters via ServeHTTP
Plumego implements http.Handler.
When ServeHTTP is called:
- Plumego gains control of request execution
- No routing or middleware has run yet
- No Context exists yet
This is the only entry point into Plumego.
Step 3: Context Creation
Plumego immediately creates a new Context:
- Bound to this request
- Bound to this response writer
- Guaranteed unique
- Guaranteed request-scoped
From this point on, all framework interaction goes through Context.
Step 4: Global Middleware (Before Phase)
Global middleware executes first, in registration order.
Typical responsibilities:
- Trace ID generation
- Logging (request start)
- Panic recovery setup
- Timeouts / limits
At this stage:
- No route has been selected yet
- Middleware should not assume application intent
- Middleware may stop execution early
If a middleware does not call next(), the lifecycle ends here.
Step 5: Route Matching
If global middleware allows execution to continue:
- The router matches the request by method + path
- Exactly one route is selected, or none
Outcomes:
- Match → proceed
- No match → 404
- Method mismatch → 405
Routing is deterministic and side-effect free.
Step 6: Scoped Middleware (Before Phase)
Once a route is matched:
- Route-level or group-level middleware runs
- Execution order is explicit and predictable
Typical responsibilities:
- Authentication
- Authorization (coarse-grained)
- Feature gating
At this point:
- Route intent is known
- Business context may be established
- Middleware may still abort execution
Step 7: Handler Execution
If all middleware allows execution:
- The handler is invoked exactly once
- Handler receives the Context
- Handler performs boundary translation
- Handler invokes usecases
- Handler writes the response
Plumego guarantees:
- No retries
- No duplicate calls
- No hidden wrapping
If a handler panics, recovery middleware (if present) handles it.
Step 8: Scoped Middleware (After Phase)
After the handler returns:
- Scoped middleware executes its “after” logic
- Cleanup, metrics, or tracing may occur
Execution order mirrors the “before” phase, in reverse.
Step 9: Global Middleware (After Phase)
Finally:
- Global middleware executes its “after” logic
- Logging middleware may record completion
- Timers stop
- Metrics are emitted
At this point, the response is complete.
Step 10: Context Disposal
After response completion:
- Context is no longer referenced
- No further code should access it
- Garbage collection may reclaim it later
Context lifetime is strictly bounded to the request.
Lifecycle Guarantees
Plumego guarantees that for each request:
- Exactly one Context is created
- Middleware order is deterministic
- At most one handler is executed
- No hidden phases exist
- No implicit retries occur
These guarantees are stable across versions.
What Is Not Part of the Lifecycle
Deliberately excluded:
- Background tasks
- Async job execution
- Scheduled work
- Out-of-band side effects
If something happens outside this lifecycle,
it must be initiated explicitly by your code.
Lifecycle and Error Handling
Errors affect the lifecycle as follows:
- Boundary errors → handled by middleware or handlers
- Business errors → returned by usecases, translated by handlers
- Panics → caught by recovery middleware (if installed)
Plumego itself does not reinterpret errors.
Lifecycle and Concurrency
Each request lifecycle is independent.
Plumego guarantees:
- No shared Contexts
- No cross-request mutation
- Safe concurrent execution
Concurrency issues arise only from user code.
Why the Lifecycle Is Explicit
Many frameworks add hidden phases:
- Implicit validation
- Implicit authorization
- Implicit retries
- Implicit hooks
Plumego avoids these because:
Hidden lifecycle steps make systems harder to reason about than hidden logic.
Explicit lifecycle is a core design value.
Using the Lifecycle as a Debugging Tool
When debugging, always ask:
- Did the request enter Plumego?
- Which middleware ran?
- Did routing succeed?
- Did the handler run?
- Where did execution stop?
With an explicit lifecycle, the answer is always visible in code.
Summary
In Plumego:
- Request lifecycle is linear and explicit
- Control flow is visible
- Middleware defines execution
- Routing selects intent
- Handlers execute once
- Context is bounded and disposable
Once you internalize this lifecycle,
Plumego becomes predictable under all conditions.
Core Layer: Complete Mental Model
With HTTP Server, Context, Router, Middleware, and Lifecycle covered,
you now possess the entire executable mental model of Plumego’s core.
Nothing else runs unless you write it.