Request Lifecycle
Every framework, no matter how small, defines a request lifecycle.
Understanding this lifecycle is the key to using Plumego correctly —
and to avoiding subtle bugs that only appear in production.
This document describes, step by step, what happens from the moment a request arrives to the moment a response is sent.
Why the Request Lifecycle Matters
Many problems in backend systems come from misunderstanding where things happen:
- Logging at the wrong stage
- Authentication running too late
- Context values leaking across requests
- Responses being written multiple times
- Errors handled inconsistently
Plumego’s lifecycle is intentionally simple and explicit so that:
- Execution order is predictable
- Side effects are visible
- Responsibility is clearly assigned
High-Level Overview
At a high level, every request in Plumego follows this flow:
Incoming HTTP Request
↓
net/http Server
↓
Plumego Router
↓
Middleware Chain
↓
Context Creation
↓
Handler Execution
↓
Response Written
↓
Request Ends
There are no hidden stages beyond this diagram.
Stage 1: net/http Accepts the Request
Plumego does not implement its own HTTP server.
When you call:
app.Run(":8080")
Plumego internally creates and starts a standard http.Server.
This means:
- Connection handling follows Go’s standard behavior
- Timeouts, cancellation, and keep-alive are handled by
net/http - The base
context.Contextoriginates from the standard library
Plumego begins execution after the request has already entered the Go HTTP stack.
Stage 2: Routing and Handler Selection
Once the request reaches Plumego:
- The HTTP method is inspected
- The request path is matched against registered routes
- The corresponding handler is selected
Important characteristics:
- Only explicitly registered routes are considered
- Matching is deterministic and ordered
- No reflection or annotation-based scanning is involved
If no route matches, Plumego immediately returns a 404 response.
Stage 3: Middleware Chain Execution
If middleware is registered, it executes before the handler.
Middleware in Plumego is:
- Explicitly registered
- Executed in a predictable order
- Applied uniformly to matching routes
Execution order looks like this:
Request →
Middleware A →
Middleware B →
Handler →
Middleware B →
Middleware A →
Response
Key properties:
- Middleware can short-circuit the request
- Middleware can modify context
- Middleware must explicitly call the next function to continue
Nothing runs implicitly.
Stage 4: Context Creation and Scope
Before invoking the handler, Plumego creates a Context instance.
This context:
- Wraps
http.Requestandhttp.ResponseWriter - Embeds
context.Context - Exists for exactly one request
- Is never reused or shared
Why this matters
- Context values cannot leak between requests
- Cancellation is request-scoped
- Middleware and handlers operate on the same context instance
Plumego treats the context as the single unit of request state.
Stage 5: Handler Execution
The handler is where application logic begins.
In Plumego, handlers are expected to:
- Read request data
- Invoke domain or use-case logic
- Write the response
Handlers should not:
- Contain complex business rules
- Manage global state
- Depend deeply on framework internals
They are the boundary between HTTP and the application core.
Stage 6: Response Writing
The response is written explicitly by the handler (or middleware).
When a handler calls a response helper (for example, ctx.String):
- Status code is set
- Headers are written
- Body is sent to the client
Once the response is written:
- Further writes are ignored or rejected
- The request lifecycle is effectively complete
Plumego does not perform post-processing on responses.
Stage 7: Request Completion
After the handler returns:
- Control returns to the middleware chain (if any)
- The HTTP server finalizes the request
- The connection may be reused or closed by
net/http
Plumego performs no background cleanup beyond what is required for the request.
Lifecycle Invariants
Plumego enforces several important invariants:
- Each request has exactly one context
- Each request executes handlers at most once
- Middleware order is fixed and visible
- Response writing is explicit
- No background goroutines are spawned implicitly
These invariants are essential for reasoning about behavior under load and failure.
What the Lifecycle Does Not Include
The request lifecycle intentionally excludes:
- Automatic retries
- Background jobs
- Asynchronous side effects
- Global state mutation
If these behaviors are required, they must be implemented explicitly and consciously.
Common Mistakes to Avoid
Writing responses in multiple places
Ensure that:
- Only one component writes the final response
- Middleware that short-circuits does not allow the handler to continue
Performing heavy work before routing
Expensive operations should occur after route matching and authorization.
Treating middleware as business logic
Middleware should handle cross-cutting concerns only.
Business rules belong in the application core.
Why Plumego Keeps the Lifecycle Simple
Complex lifecycles are difficult to reason about and debug.
Plumego intentionally avoids:
- Multiple handler phases
- Implicit hooks
- Framework-managed background tasks
Simplicity here enables flexibility elsewhere.
Summary
The Plumego request lifecycle is:
- Linear
- Explicit
- Predictable
- Closely aligned with Go’s standard library
If you understand this lifecycle, you understand Plumego’s core behavior.
Everything else in the framework builds on this foundation.
Next
With the lifecycle understood, the next step is to examine the most important building block in detail:
→ Context