Docs Request Lifecycle

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:

  1. Did the request enter Plumego?
  2. Which middleware ran?
  3. Did routing succeed?
  4. Did the handler run?
  5. 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.