Hacker DirectoryHacker Directory

WEB / WEB-16.01

Web server, runtime, and execution model

The server accepting HTTP and the runtime executing application decisions serve different roles. Trace a request from proxy to callback.

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mechanism

Read every scenario without motion

Proxy upstream

  1. Public read ready

    Duru prepares GET /notes; neither edge nor application has received this request yet.

    Client / Duru
    GET /notes ready
    Edge server
    No request
    Application runtime
    No request
    Execution state
    No handler
  2. Edge arrival

    The client GET reaches the edge while upstream state still has no request.

    Client / Duru
    Waiting response
    Edge server
    GET received
    Application runtime
    No request
    Execution state
    No handler
  3. Select upstream

    The edge locally selects upstream routing for /notes and prepares forwarding.

    Client / Duru
    Waiting response
    Edge server
    Upstream selected
    Application runtime
    No request
    Execution state
    No handler
  4. Upstream arrival

    The second HTTP GET arrives at the application runtime, not as an in-process callback arrow.

    Client / Duru
    Waiting response
    Edge server
    Waiting upstream
    Application runtime
    GET /notes received
    Execution state
    Handler pending
  5. Local handler

    The runtime local handler produces Runtime note with 12 UTF-8 content bytes.

    Client / Duru
    Waiting response
    Edge server
    Waiting upstream
    Application runtime
    Response200 ready
    Execution state
    Handler result Runtime note
  6. Upstream response

    Application response200/content reaches the edge while the client has not received its response.

    Client / Duru
    Waiting response
    Edge server
    200 Runtime note received
    Application runtime
    Response delivered upstream hop
    Execution state
    Handler complete
  7. Client response

    The edge response200/content reaches the client, preserving completion of two distinct HTTP hops.

    Client / Duru
    200 Runtime note received
    Edge server
    Response delivered client hop
    Application runtime
    Upstream exchange complete
    Execution state
    Handler complete

Edge static

  1. Static read ready

    The client selects a public /static/note read with no application request available.

    Client / Duru
    GET static ready
    Edge server
    No request
    Application runtime
    No request
    Execution state
    Unused
  2. Edge arrival

    GET reaches the edge, where the selected route belongs to static serving.

    Client / Duru
    Waiting response
    Edge server
    GET static received
    Application runtime
    No request
    Execution state
    Unused
  3. Local static read

    The edge produces harmless Static note from its selected content without upstream dispatch.

    Client / Duru
    Waiting response
    Edge server
    200 Static note ready
    Application runtime
    No request
    Execution state
    Static source supplied
  4. Client response

    Static response200/content reaches the client without application-runtime participation.

    Client / Duru
    200 Static note received
    Edge server
    Client response delivered
    Application runtime
    No request
    Execution state
    Static source supplied
  5. Owner outcome

    The client has received the 200 Static note body. No upstream dispatch is known from this example’s edge routing decision; status and body alone do not tell the client whether an application handler ran. This scene shows neither DOM nor rendered pixels.

    Client / Duru
    200 Static note received
    Edge server
    Exchange complete
    Application runtime
    No request
    Execution state
    Static ownership recorded

Async CPU section

  1. Bounded CPU job

    The selected Node callback context prepares a 10000-term sum and queued event callback.

    Client / Duru
    No HTTP modeled
    Edge server
    Unused
    Application runtime
    Job ready; event queued
    Execution state
    Sum pending
  2. Async entry

    The async function enters CPU work without an initial await; the queued callback cannot intervene.

    Client / Duru
    No HTTP modeled
    Edge server
    Unused
    Application runtime
    cpu-start; main JS active
    Execution state
    Sum in progress
  3. CPU completes

    The 1..10000 sum completes as 50005000 with no other-CPU or timer-duration claim.

    Client / Duru
    No HTTP modeled
    Edge server
    Unused
    Application runtime
    cpu-end; main JS active
    Execution state
    Sum50005000
  4. Caller resumes

    Caller-after-call is recorded after the function returns a Promise; computation is already complete.

    Client / Duru
    No HTTP modeled
    Edge server
    Unused
    Application runtime
    caller-after-call
    Execution state
    Sum50005000
  5. Await continuation

    In this selected context, awaiting the resolved result continues before the queued event callback.

    Client / Duru
    No HTTP modeled
    Edge server
    Unused
    Application runtime
    caller-after-await
    Execution state
    Sum50005000
  6. Queued callback

    The event callback runs after synchronous CPU work; async does not imply automatic parallel execution.

    Client / Duru
    No HTTP modeled
    Edge server
    Unused
    Application runtime
    event-callback observed
    Execution state
    Sum50005000; duration unmeasured

ACTORS · STATE · DATA FLOW

Server roles are broader than product names

A web server is the role that accepts HTTP requests and returns appropriate responses, serving static content or forwarding work. An application server connects requests to application logic and produces its result. These roles do not always require two machines, two processes, or separate products. A Node http.createServer callback lets one process handle both HTTP serving and application execution. A framework organizes routing and middleware; it does not replace the runtime code-execution and I/O capabilities.

For Duru public /notes route, the edge forwards a request upstream and the application runtime produces Runtime note. For /static/note, the edge returns Static note itself without an application request. Both can exist under one external origin. Assuming every response came from backend business logic, or that a web server only serves files, loses this distinction.

Python HTTPServer listens at a socket and dispatches to a handler; ThreadingHTTPServer uses ThreadingMixIn for threaded handling. This does not mean every Python application has that execution model. Similarly, a web/application server label alone does not identify which process listens at a port or which runtime executes application code.

A reverse proxy creates another HTTP hop

A reverse proxy accepts the client request, sends its own request to a selected upstream, receives the upstream response, and responds to the client. Client-to-edge and edge-to-application are separate exchanges, not one socket or an in-process function call. The fixture preserves method/path and harmless content. Real proxies may also map URIs, cache, buffer, or apply connection policies, depending on configuration.

A TLS-terminating edge and plaintext upstream do not automatically share the same confidentiality boundary; these local HTTP hops do not measure a TLS deployment. Proxy routing does not automatically establish application user/object authorization. Accepting identity or forwarded metadata across trust boundaries needs a deployment contract; proxy-trust details belong to WEB-18.

The Static note response never goes upstream. In the normal proxy branch, Runtime note can reach the edge before the client receives it. The scene preserves these different arrivals. Seeing a request at the edge alone proves neither handler execution nor browser consumption of the response.

Async work is not automatic CPU parallelism

Default Node JavaScript callbacks run on one event-loop thread. Suitable network I/O can be offloaded to the kernel, and selected filesystem/crypto APIs use the libuv worker pool. This does not automatically move a long application JavaScript loop into that pool. An async function executes synchronously until its first await; returning a Promise does not place that part on another CPU.

The artifact sum of 1..10000 is 50005000. The selected async function finishes this bounded computation without an await, so a queued event callback cannot run in its synchronous middle. No duration or throughput is invented. worker_threads offers a separate execution choice for CPU-heavy JavaScript; pool/thread overhead and result messaging remain decisions. More processes or threads do not guarantee unlimited capacity or correct shared state.

A process has its own application-memory state; changing a local variable in a separate process does not automatically change the parent. Threads relate to one process resources, while each JavaScript Worker can have separate globals/state and explicit sharing/transfer mechanisms. Worker_threads, the libuv worker pool, and browser Web Workers are different APIs. Sharing state across deployment replicas needs explicit ownership/store contracts rather than an in-memory variable assumption.

2. Red · Trust & Impact

Read every scenario without motion

Async CPU

  1. The async computation was selected

    The fixture sums 1..10000 in an async function with no first await. The async keyword alone does not create CPU parallelism.

    Call/route context
    Async function
    Runtime/edge owner
    CPU not started
    Callback/policy boundary
    Callback pending
  2. The synchronous section began

    The trace starts with cpu-start. This section runs in current JavaScript execution; the callback has not intervened.

    Call/route context
    Call continuation pending
    Runtime/edge owner
    cpu-start
    Callback/policy boundary
    Callback pending
  3. The bounded CPU section completed

    cpu-end gives sum=50005000. Returning a Promise has not moved the computation onto a separate thread.

    Call/route context
    Call continuation pending
    Runtime/edge owner
    cpu-end; sum=50005000
    Callback/policy boundary
    Callback pending
  4. Caller continuation was separated

    caller-after-call precedes caller-after-await. Await does not retroactively make the earlier synchronous CPU section nonblocking.

    Call/route context
    caller-after-await
    Runtime/edge owner
    CPU completed
    Callback/policy boundary
    Callback pending
  5. The queued callback ran later

    event-callback ends this selected trace. With durationMs=null, the ordering is not a production-latency measurement.

    Call/route context
    Caller continued
    Runtime/edge owner
    CPU completed
    Callback/policy boundary
    event-callback
  6. Capacity controls stayed tied to the execution model

    Callback work should be bounded; CPU ownership can be assigned to a worker when needed. The fixture keeps parallelCPUClaim=false and runs no load attack.

    Call/route context
    Execution order known
    Runtime/edge owner
    Automatically parallel=false
    Callback/policy boundary
    Latency/capacity not measured

Static role

  1. The static-response role was selected

    Duru selects /static/note. The edge owns the response in this public example; an application handler is not automatically called.

    Call/route context
    /static/note
    Runtime/edge owner
    Route not examined
    Callback/policy boundary
    No application outcome
  2. The static-route outcome was read

    staticExchange has upstreamReached=false. Edge content serving does not prove that Node application identity or object policy ran.

    Call/route context
    /static/note
    Runtime/edge owner
    Static owner: edge
    Callback/policy boundary
    Upstream not reached
  3. The representation was separated by its public scope

    The body is Static note with responseStatus=200. This normal public response does not establish safe use of the same serving contract for personalized data.

    Call/route context
    Public static representation
    Runtime/edge owner
    Status=200; 11 content octets
    Callback/policy boundary
    Application policy not shown
  4. Status was not promoted to authority

    Edge 200 describes only the selected static representation. Application permission checks or session acceptance are not inferred from it.

    Call/route context
    Public static representation
    Runtime/edge owner
    Edge source known
    Callback/policy boundary
    No inferred authenticated grant
  5. The sensitive-route contract stayed separate

    Personalized responses need explicit route ownership, identity and resource policy. A proxy or web-server product name is not proof of that contract.

    Call/route context
    Public static fixture only
    Runtime/edge owner
    Route boundary explicit
    Callback/policy boundary
    Sensitive policy requires separate evidence
  6. The serving conclusion closed with its source

    This case explains no-upstream behavior for a selected static branch. It does not create a general rule treating a missing application log as proof of no upstream dispatch.

    Call/route context
    Known: static branch
    Runtime/edge owner
    Known: no upstream dispatch
    Callback/policy boundary
    No application authorization claim

ASSUMPTION · BOUNDARY · CONTROL

Shared execution capacity is a boundary

Synchronous JavaScript in one handler can delay the same event-loop callback queue. The broken assumption is that the async keyword makes all work nonblocking; sufficiently large normal computation can affect other requests. Impact is availability latency depending on runtime, concurrency, and workload. This 10000-term example is neither a load attack nor a production benchmark.

Choose bounded callback work, suitable I/O APIs, and CPU-work ownership separately. The worker pool also has limited capacity; a new thread for every job is not an automatic solution. Worker execution needs result correlation and lifecycle, without assuming memory is shared across replicas. State invisible to another process alone proves neither data loss nor compromise.

Identify the owner of served content

Treating static content as the result of an application permission check confuses hop and handler ownership. Public Static note is normal; with personalized data the same assumption can misinterpret confidentiality or stale results. Letting an edge route/cache choice stand in for application policy requires an explicit correct contract. A product name or edge status 200 is not proof of that contract.

Successfully forwarding a request still leaves upstream failure and incomplete client delivery as separate conditions. Keep correlation metadata per hop, distinguish static versus upstream content, and read response arrivals separately. This keeps the component producing a result distinct from the component receiving it rather than collapsing both into one success label.

3. Blue · Secure development & defense

Read every scenario without motion

Response hops

  1. The proxy-exchange evidence was selected

    proxyExchange carries clientPath and upstreamPath for /notes. Client status and upstream observation are not the same observation point.

    Runtime observation
    Proxy exchange /notes
    Hop/process review
    Hop map not examined
    Evidence scope
    Client knowledge not read
  2. The upstream-dispatch field was read

    upstreamReached=true is the routing outcome for this branch. A missing correlation log does not by itself establish that it was false.

    Runtime observation
    Proxy exchange /notes
    Hop/process review
    Upstream reached=true
    Evidence scope
    Client knowledge not read
  3. Body source and byte count were separated

    The Runtime note representation is 12 UTF-8 content octets. This is not the size of HTTP wrappers, headers or network packets.

    Runtime observation
    Runtime note
    Hop/process review
    Content octets=12
    Evidence scope
    Body source: runtime
  4. Response-arrival ordering was compared

    upstreamArrivalBeforeClientArrival=true describes the order in this two-hop example. Edge receipt is not yet the moment the client learns the body.

    Runtime observation
    Declared proxy exchange
    Hop/process review
    Upstream arrival before client
    Evidence scope
    Knowledge boundaries separate
  5. Browser-render evidence was not added

    Declared response status/body does not show DOM or rendered pixels. Runtime, edge and browser observations are correlated using their own sources.

    Runtime observation
    Status/body declared
    Hop/process review
    Hop ordering declared
    Evidence scope
    UNKNOWN: DOM/pixels
  6. The proxy-evidence scope was closed

    This ledger explains ordinary forwarding owners; it is not a production proxy access-log schema or throughput result.

    Runtime observation
    Known: runtime body source
    Hop/process review
    Known: selected hop order
    Evidence scope
    Runtime/browser generalization withheld

Process memory

  1. The process-state observation was selected

    The memory fixture uses separate aliases proc-main and proc-child. Ordinary objects in two processes are not one mutable state.

    Runtime observation
    proc-main / proc-child
    Hop/process review
    State not read
    Evidence scope
    No shared-memory evidence
  2. Initial parent state was read

    parentStateBefore=7 describes parent ownership. A future child update is not assumed to transfer automatically to the parent.

    Runtime observation
    Parent before=7
    Hop/process review
    Child separate process
    Evidence scope
    No shared-memory evidence
  3. The child outcome was read separately

    childStateAfter becomes 42. This ordinary state change belongs to the child process; it is not shown as shared-store state or an explicit message outcome.

    Runtime observation
    Parent before=7
    Hop/process review
    Child after=42
    Evidence scope
    SharedMemoryUsed=false
  4. Parent after-state was compared

    parentStateAfter remains 7. The child change did not mutate the parent; calling this alone data loss or compromise would be incorrect.

    Runtime observation
    Parent after=7
    Hop/process review
    Child after=42
    Evidence scope
    Ownership scope consistent
  5. Worker and process roles were not equated

    Worker threads, separate processes and shared memory are different choices. This fixture is limited to a separate process with sharedMemoryUsed=false.

    Runtime observation
    Separate-process profile
    Hop/process review
    No implicit shared object
    Evidence scope
    Other IPC/worker behavior unknown
  6. The memory conclusion remained bounded

    The selected before/after states support separate ownership. Replicas, durable storage, restart recovery or all cancellation behavior cannot be inferred from these two numbers.

    Runtime observation
    Known: parent retained 7
    Hop/process review
    Known: child reached 42
    Evidence scope
    No distributed durability claim

IMPLEMENTATION · SECURITY CONTROL · VERIFICATION

Build the role and hop ledger

First observe the listening endpoint and where the selected request dispatches. For /notes, correlate harmless edge/application request observations; for /static/note, expect no increase in application request count. Client status/body and edge upstream observation are different telemetry points. Do not present native API event names as a real proxy access-log schema; field mapping depends on the server product.

Read method/path, response status, and bytes separately in the request callback. Runtime note is 12 UTF-8 bytes; preserve its producing hop and the encoded content measured. Read WEB-16.03 for why response finish differs from client arrival. Missing correlation does not automatically prove the upstream never ran; in the selected static branch, the routing decision supports no-upstream evidence.

Separate execution model from measurement

Record entry/exit, caller continuation, and queued callback order for the async CPU fixture. Independently check the sum with n(n+1)/2; looking fast is not the pass criterion. Reporting queue effects as production latency needs actual workload and timing measurements. Small bounded work is enough to explain an async function synchronous portion.

Keep parent state of 7 and separate-process state of 42 as different ownership records; aliases suffice without actual PIDs. Name the thread/worker API explicitly. Without shared memory, ordinary object mutation is not shared state. Moving long computation to a worker also needs normal result, cancellation, and failure boundaries; adding async alone does not create that lifecycle.

The artifact XPath counts work observations marked synchronousCPU=true together with automaticallyParallel=true. Normal async CPU evidence yields 0 and an incorrect-interpretation fixture yields 1. This XML is an instructional schema, not an event-loop telemetry provider. A missing work element also yields 0 and cannot prove correct runtime behavior.

Bound execution cost at the request boundary

Async does not remove CPU cost. Define the accepted request size and maximum work before entering the handler; avoid unbounded computation on the event loop. Use appropriate asynchronous APIs for network and disk I/O, while CPU work may move to a worker pool. Bound its pending jobs and define time limits and failure behavior; unlimited worker creation is not a safe capacity policy.

The correct sum for 1..10000 and callback order explain this small operation. For work outside an admitted bound, separately verify that no handler or worker dispatch occurred; worker failure must not produce a normal result. Observe accepted output separately from queue delay. Missing dispatch or completion evidence does not prove absence of work. This ordering example does not measure service capacity, enforce timeouts or establish worker isolation.

NOW APPLY IT TO THE CASE

Which authority is not supplied by async or an edge response?

A bounded CPU trace and public static route show different execution boundaries. Hop sources and process-memory ownership are read using their own evidence.

Reconstruct decision order for input, server processing and response in the case. Parsed or valid data is not a completed operation; identify each owner and its condition.

Open the related case file ↗

READ THE EXAMPLE TOGETHER

Server-role and execution ledger

Select a field and examine what it supports and where the evidence ends.

Read the raw artifact and field explanations
{
  "roles": {
    "client": "Duru",
    "edge": "HTTP reverse-proxy or static-serving role",
    "runtime": "Node application execution role",
    "framework": "not installed; manual handler organization"
  },
  "proxyExchange": {
    "clientPath": "/notes",
    "upstreamPath": "/notes",
    "upstreamReached": true,
    "responseStatus": 200,
    "body": "Runtime note",
    "contentOctets": 12,
    "upstreamArrivalBeforeClientArrival": true
  },
  "staticExchange": {
    "clientPath": "/static/note",
    "upstreamReached": false,
    "responseStatus": 200,
    "body": "Static note",
    "contentOctets": 11
  },
  "cpu": {
    "n": 10000,
    "sum": 50005000,
    "asyncFunctionFirstAwaitAbsent": true,
    "selectedTrace": [
      "cpu-start",
      "cpu-end",
      "caller-after-call",
      "caller-after-await",
      "event-callback"
    ],
    "parallelCPUClaim": false,
    "durationMs": null
  },
  "memory": {
    "parentProcessAlias": "proc-main",
    "separateProcessAlias": "proc-child",
    "parentStateBefore": 7,
    "childStateAfter": 42,
    "parentStateAfter": 7,
    "sharedMemoryUsed": false
  },
  "selector": {
    "language": "XPath",
    "xml": "<observations><work async=\"true\" synchronousCPU=\"true\" automaticallyParallel=\"false\"/></observations>",
    "xpath": "count(/observations/work[@synchronousCPU=\"true\" and @automaticallyParallel=\"true\"])",
    "expected": 0,
    "positiveFixtureXml": "<observations><work async=\"true\" synchronousCPU=\"true\" automaticallyParallel=\"true\"/></observations>",
    "positiveExpected": 1,
    "scope": "Only authored protocol-decision observations, not product log field names or a live HTTP capture.",
    "missingFieldBehavior": "Missing observation is insufficient evidence; zero matches is not proof of correct runtime behavior."
  }
}
roles
HTTP, runtime, and framework roles need not be one product/process.
proxyExchange / staticExchange
Upstream arrival and edge-owned responses follow different paths.
cpu / memory
Bounded sum/order and ordinary process-memory ownership.

Inert public-note ledger; selected timer order is context-bound. It does not measure TLS, production capacity, or arbitrary process isolation.

Two reality checks

An async function automatically moves a long CPU loop to another thread.

JavaScript runs synchronously until the first await; CPU worker execution is a separate choice.

Web and application servers are always separate machines.

They are roles: one process can serve both, or a reverse proxy can create a separate hop.

YOUR TURN

Work through this story.

Predict the outcome, find the evidence boundary, and explain it in your own words.

An async function performs a CPU sum before its first await. Is CPU work automatically parallel while the caller waits for the call to return?

  1. Yes; the async label moves the whole function body to a worker thread.
  2. No; the selected trace has cpu-start/cpu-end before caller-after-call.
Read the explained answer

No; the selected trace has cpu-start/cpu-end before caller-after-call. — The async keyword does not move synchronous CPU to another thread; parallelCPUClaim=false.

The child process set state 42; why did parent state 7 stay unchanged?

Selected lesson artifact fields; teaching example

memory
{"parentProcessAlias":"proc-main","separateProcessAlias":"proc-child","parentStateBefore":7,"childStateAfter":42,"parentStateAfter":7,"sharedMemoryUsed":false}
  1. Process-local states are separate; sharedMemoryUsed=false.
  2. A shared application name provides one heap across all processes.
Read the explained answer

Process-local states are separate; sharedMemoryUsed=false. — A child-state mutation does not change parent-object ownership; IPC/shared memory must be established separately.

What does the upstreamReached difference show between static serving and reverse-proxy exchange? Why are Web/application server roles not host counts?

Read the explained answer

The static branch shows the edge supplying a body without upstream access; the proxy branch shows an upstream response reaching the edge before the client. Web-server/application-runtime roles may run in the same or different processes/hosts. Manual handler organization does not prove a framework is installed, and the sum trace is not a performance benchmark.

□ I separated role from host/process placement.

□ I kept upstream and client arrivals separate.

Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples

Sources and scope