Hacker DirectoryHacker Directory

WEB / WEB-20.01

Monoliths, three-tier architecture, and SPAs

Deployment units, logical roles, and browser rendering are different axes; compare server HTML and SPA data flows for one public note.

CORE · RED · BLUE · ARTIFACT · PRACTICE

1. Core · Mechanism

Read every scenario without motion

Server HTML

  1. Page intent

    The browser prepares to request a public SSR page; the server does not yet know the target.

    Browser frontend
    No document; note intent
    Application server
    No received target
    Local application service
    Service idle
    Local data owner
    Public Tea note available
  2. Prepare request

    The sender prepares its selected GET target; receiver values stay at previous completion during motion.

    Browser frontend
    Prepared GET /server-note
    Application server
    No received target
    Local application service
    Service idle
    Local data owner
    Public Tea note available
  3. Request arrives

    The request reaches the server. The server now knows the GET /server-note target; the service and public note store have not changed.

    Browser frontend
    Prepared GET /server-note
    Application server
    Received GET /server-note
    Local application service
    Service idle
    Local data owner
    Public Tea note available
  4. Local service read

    Server service/data calls are local in the selected process; no physical-tier packet is drawn.

    Browser frontend
    Prepared GET /server-note
    Application server
    Received GET /server-note
    Local application service
    Known public note read
    Local data owner
    Public Tea note available
  5. Prepare HTML

    The server prepares title text in source HTML; the browser has not yet received its document content.

    Browser frontend
    Prepared GET /server-note
    Application server
    Prepared200 HTML Tea note
    Local application service
    Known public note read
    Local data owner
    Public Tea note available
  6. HTML arrives

    The authored snapshot receives a complete response body; parsing and live DOM are separate local stages.

    Browser frontend
    Received200 HTML body
    Application server
    Prepared200 HTML Tea note
    Local application service
    Known public note read
    Local data owner
    Public Tea note available
  7. Parse/view

    The browser displays Tea note from the received HTML. This visible title comes from the server-rendered response.

    Browser frontend
    Projected DOM text: Tea note
    Application server
    Prepared200 HTML Tea note
    Local application service
    Known public note read
    Local data owner
    Public Tea note available

SPA data/view

  1. Shell completed

    This SPA case starts after initial HTML startup with projected Loading; no note API result exists yet.

    Browser frontend
    Startup HTML200 received; projected Loading
    Application server
    No API target received
    Local application service
    Service idle
    Local data owner
    Selected public note store
  2. Prepare data GET

    The frontend prepares a selected API request; initial HTML success does not determine data availability.

    Browser frontend
    Loading; prepared GET /api/notes/tea
    Application server
    No API target received
    Local application service
    Service idle
    Local data owner
    Selected public note store
  3. API request arrives

    The conceptual API target becomes known at server arrival; backend ownership differs from browser intent.

    Browser frontend
    Loading; prepared GET /api/notes/tea
    Application server
    Received GET /api/notes/tea
    Local application service
    Service idle
    Local data owner
    Selected public note store
  4. Local availability

    The selected service determines public-record availability locally; the browser is not the database owner.

    Browser frontend
    Loading; prepared GET /api/notes/tea
    Application server
    Received GET /api/notes/tea
    Local application service
    Known Tea note available
    Local data owner
    Selected public note store
  5. Prepare JSON

    The backend prepares status/media type/body; a prepared response does not give the frontend its new value.

    Browser frontend
    Loading; prepared GET /api/notes/tea
    Application server
    Prepared200 JSON Tea note
    Local application service
    Known Tea note available
    Local data owner
    Selected public note store
  6. API response arrives

    The authored complete-body snapshot arrives; Fetch fulfillment remains distinct from HTTP success.

    Browser frontend
    Received200 Response/body; still Loading
    Application server
    Prepared200 JSON Tea note
    Local application service
    Known Tea note available
    Local data owner
    Selected public note store
  7. Status and note accepted

    The frontend accepts status 200 and the expected note shape. The note is parsed; the DOM update is the next step.

    Browser frontend
    Status/body/schema checked; note parsed
    Application server
    Prepared200 JSON Tea note
    Local application service
    Known Tea note available
    Local data owner
    Selected public note store
  8. View commit

    The frontend projects Tea note into the view after accepting the JSON response. Loading is replaced by the note title.

    Browser frontend
    Projected DOM text: Tea note
    Application server
    Prepared200 JSON Tea note
    Local application service
    Known Tea note available
    Local data owner
    Selected public note store

SPA API404

  1. Shell completed

    This SPA case starts after initial HTML startup with projected Loading; no note API result exists yet.

    Browser frontend
    Startup HTML200 received; projected Loading
    Application server
    No API target received
    Local application service
    Service idle
    Local data owner
    Selected public note store
  2. Prepare data GET

    The frontend prepares a selected API request; initial HTML success does not determine data availability.

    Browser frontend
    Loading; prepared GET /api/notes/missing
    Application server
    No API target received
    Local application service
    Service idle
    Local data owner
    Selected public note store
  3. API request arrives

    The conceptual API target becomes known at server arrival; backend ownership differs from browser intent.

    Browser frontend
    Loading; prepared GET /api/notes/missing
    Application server
    Received GET /api/notes/missing
    Local application service
    Service idle
    Local data owner
    Selected public note store
  4. Local availability

    The selected service determines public-record availability locally; the browser is not the database owner.

    Browser frontend
    Loading; prepared GET /api/notes/missing
    Application server
    Received GET /api/notes/missing
    Local application service
    Known public note missing
    Local data owner
    Selected public note store
  5. Prepare JSON

    The backend prepares status/media type/body; a prepared response does not give the frontend its new value.

    Browser frontend
    Loading; prepared GET /api/notes/missing
    Application server
    Prepared404 JSON not-found
    Local application service
    Known public note missing
    Local data owner
    Selected public note store
  6. API response arrives

    The authored complete-body snapshot arrives; Fetch fulfillment remains distinct from HTTP success.

    Browser frontend
    Received404 Response/body; still Loading
    Application server
    Prepared404 JSON not-found
    Local application service
    Known public note missing
    Local data owner
    Selected public note store
  7. 404 prevents note update

    The frontend receives the 404 Response, but its status check rejects a successful note update. The next step replaces Loading with an error view.

    Browser frontend
    Status guard rejected; no successful note
    Application server
    Prepared404 JSON not-found
    Local application service
    Known public note missing
    Local data owner
    Selected public note store
  8. Unavailable message shown

    The frontend projects Note unavailable into the view. It does not display a new note title as if the API request succeeded.

    Browser frontend
    Projected message: Note unavailable
    Application server
    Prepared404 JSON not-found
    Local application service
    Known public note missing
    Local data owner
    Selected public note store

ACTORS · STATE · DATA FLOW

Deployment units and layers/tiers are different axes

A monolith groups core application behavior in one development/release deployment unit. This does not mean one file or binary: the unit can contain modules, projects, and artifacts, and horizontal replicas can run it in multiple processes or machines. Microsoft .NET examples describe instance core behavior in its own process, not a requirement that the whole topology has one process. Databases and other dependencies may be separate. No framework or deployment changes occur here.

Presentation, application/business, and data access are three logical responsibilities. Layers define code responsibilities and dependencies; tiers define physical deployment boundaries. A three-tier architecture can place these responsibilities in physical tiers, and one tier can contain multiple logical layers. Three boxes do not prove three machines or independently deployed services. Our native fixture keeps server roles in one local builder/service process with a synthetic memory dictionary. Logical roles are visible without claiming a physical cluster.

The frontend renders and handles interaction in a user agent; the backend serves endpoints and owns business/data decisions. Frontend validation or loaded JSON does not replace permission or invariant decisions. One application server can serve both SSR HTML and a JSON API; SPA does not require microservices or separate backend deployment. Monolith, three-tier, and SPA are not mutually exclusive product choices: deployment, placement, and UI behavior answer different questions.

Initial HTML, later data, and DOM are separate states

In server rendering the server reads public Tea note through service/data owners and places content into h1; after HTML arrival the browser can parse/render the DOM. Our selected SPA startup instead returns a note container with Loading text. This is one client-rendered startup, not a rule that every SPA must send empty HTML; server rendering and hydration can coexist. JavaScript can update parts of the initial document without reloading it all.

Startup HTML success is not note API success. The frontend prepares GET /api/notes/tea; route knowledge changes at the server on request arrival. The server prepares JSON, but the frontend does not know the new note until response arrival. Status/headers, body reading/JSON parsing, schema/purpose checks, and DOM update are distinct. Fetch can fulfill with a Response for HTTP errors such as 404; our status guard blocks a successful-note update. Network rejection is a different unmeasured branch.

The scene combines complete body arrival into one step; real Fetch headers can become available before the body is complete. Local status and note-shape checks then precede a plain-text DOM update. Follow what information has actually reached the browser rather than equating receipt of a response with the user seeing the intended result.

2. Red · Trust & Impact

Read every scenario without motion

200, then 404

  1. The startup document succeeded

    The apiFailure branch has startupStatus=200. This is the startup document’s HTTP outcome, not the outcome of the separate missing-note request.

    Document example
    startupStatus=200
    API outcome
    API outcome not inspected yet
    View decision
    Note view pending
  2. The API request has another outcome

    ApiTarget=/api/notes/missing has apiStatus=404. The document’s earlier 200 does not produce a successful note representation for this resource.

    Document example
    startupStatus=200
    API outcome
    apiStatus=404 / not-found
    View decision
    Success gate not met
  3. What does a fulfilled Response establish?

    The Fetch Promise model is a fulfilled Response. An HTTP 404 received this way need not be a network rejection; its HTTP status needs separate evaluation.

    Document example
    startupStatus=200
    API outcome
    fulfilled Response / status=404
    View decision
    HTTP outcome separate
  4. It was not parsed as a successful note

    NoteParsed=false. The application does not consume an error representation under the successful-note contract or use error as title.

    Document example
    startupStatus=200
    API outcome
    body: error=not-found
    View decision
    noteParsed=false
  5. The view makes its error decision

    ProjectedSuccessfulNoteCommitted=false accompanies Note unavailable. Document success and the unsuccessful note-view outcome remain separate.

    Document example
    startupStatus=200
    API outcome
    apiStatus=404
    View decision
    Note unavailable / success=false
  6. The earlier 200 gives no permission

    Receiving a document or using an SPA is not object-authorization evidence. This example compares request outcomes; permission requires the relevant resource’s server decision.

    Document example
    document delivered
    API outcome
    missing resource outcome separate
    View decision
    Startup success != object permission

Source / data

  1. The SPA source contains Loading

    Spa.sourceNoteText=Loading. Inspecting startup source alone does not establish which later data will produce the note.

    Document example
    sourceNoteText=Loading
    API outcome
    Note data not inspected yet
    View decision
    Final title pending
  2. The note has a separate JSON representation

    The API body contains id=tea, title=Tea note and version=1. These are separate input from Loading in startup HTML.

    Document example
    sourceNoteText=Loading
    API outcome
    id=tea / title=Tea note / version=1
    View decision
    View contract pending
  3. JSON parsing differs from view admission

    Parsing the body as JSON does not meet every view condition. The consumer contract establishes the expected title field and resource association.

    Document example
    startup source separate
    API outcome
    JSON representation available
    View decision
    Representation != admitted view
  4. The title comes from an admitted field

    After validation, projectedDomTextAfterValidation=Tea note is selected. It is ordinary for the final view to differ from Loading in startup source.

    Document example
    sourceNoteText=Loading
    API outcome
    title=Tea note
    View decision
    projectedDomText=Tea note
  5. The server-rendered example starts differently

    SSR sourceNoteText=Tea note means the title is already in startup HTML. Equal displayed titles do not establish equal data paths.

    Document example
    SSR sourceNoteText=Tea note
    API outcome
    SPA separate API representation
    View decision
    Same title != same path
  6. Keep the data source visible

    Keep source HTML, API representation and the consumed title separate. SPA or SSR labels do not automatically satisfy permission or safe-consumption conditions.

    Document example
    source and API records separate
    API outcome
    representation owner known
    View decision
    View contract remains explicit

ASSUMPTION · BOUNDARY · CONTROL

An architecture box proves no boundary by itself

Frontend/backend/data boxes do not prove server authorization or network isolation of a data tier. Logical class calls and remote requests differ. Server/service/data fixture calls are local and draw no packets. Browser/server request/response snapshots represent a conceptual HTTP boundary without a native capture claim.

A monolith label does not place every workload in one process, nor does SPA make browser data authoritative. Wrong assumptions can assign validation or persistence to the wrong owner. Only public Tea note exists here; there is no private endpoint or frontend-bypass workflow. Review separates behavior location from code packaging.

HTML success must not hide a later API failure

The SPA shell arrives with Loading. A selected API 404 preserves startup success while making the note result unavailable. A fulfilled promise counter is neither HTTP success nor a parsed note. Without an object matching the note schema, no successful title is projected into the DOM. This is ordinary missing-public-note behavior without real targets or malformed payloads.

An h1 in source HTML and the live DOM are separate observations. A script can change the title, an API failure can leave Loading, and later interaction can change the view again. Read the initial document, received response and DOM update separately. A visible title alone does not establish which backend request produced it.

3. Blue · Secure development & defense

Read every scenario without motion

Source / view

  1. Separate the two source examples

    A local HTML builder and HTMLParser read produce source-text observations; API status/body are the example’s separate representation. These fields are not live browser DOM observations or packet captures. SSR sourceNoteText=Tea note and SPA sourceNoteText=Loading both describe startup documents. A final browser view needs separate evidence.

    Source observation
    SSR: Tea note / SPA: Loading
    Response observation
    API response not inspected yet
    Evidence boundary
    Final browser view unknown
  2. Correlate the SPA API body

    Spa.apiTarget=/api/notes/tea has apiStatus=200. Tea note in its body describes the data resource’s outcome, not by itself application to the DOM.

    Source observation
    SPA startup: Loading
    Response observation
    API 200 / title=Tea note
    Evidence boundary
    DOM application not observed
  3. Name the modeled view outcome accurately

    ProjectedDomTextAfterValidation=Tea note is the example’s expected post-validation view. A native source-parser result is not a measurement of live browser DOM or paint.

    Source observation
    SPA source: Loading
    Response observation
    API title=Tea note
    Evidence boundary
    projectedDomTextAfterValidation=Tea note
  4. Do not substitute source for final DOM

    Loading can remain in source while application code changes the live DOM. Comparing source and final DOM requires the same document and a defined observation time.

    Source observation
    sourceNoteText=Loading
    Response observation
    API result separate
    Evidence boundary
    Source != live DOM observation
  5. Missing view observation leaves unknown

    An API response alone cannot establish the displayed title. Do not borrow another example’s projected view to complete missing browser observation.

    Source observation
    startup/API observations
    Response observation
    view observation missing
    Evidence boundary
    Final live view remains unknown
  6. Check the dependency sequence

    Correlate document, separate API result, consumer validation and view application for the same journey. Success at one stage does not establish the later stages.

    Source observation
    same document context required
    Response observation
    same API resource required
    Evidence boundary
    Each stage needs its own observation

Layer / tier

  1. Read the role map first

    A local HTML builder and HTMLParser read produce source-text observations; API status/body are the example’s separate representation. These fields are not live browser DOM observations or packet captures. Frontend describes browser presentation; backend contains endpoint/render, application service and data-owner responsibilities. These are names of logical roles.

    Source observation
    frontend: browser presentation
    Response observation
    backend: endpoint / service / data
    Evidence boundary
    Deployment layout pending
  2. A local function call is not a network hop

    Roles.serverCalls=in-process means the endpoint invokes the service in the same process. Each layer does not create another HTTP exchange.

    Source observation
    presentation responsibility
    Response observation
    serverCalls=in-process
    Evidence boundary
    Logical boundary != network hop
  3. A physical tier is another dimension

    A layer separates responsibilities and dependencies; a tier describes physical deployment separation. Multiple layers can share a tier.

    Source observation
    logical roles separate
    Response observation
    same process in this fixture
    Evidence boundary
    layersArePhysicalTiers=false
  4. Monolith does not mandate exactly one process

    The artifact records monolithIsOneMandatoryBinaryOrProcess=false. Classifying architecture by process count alone mixes deployment and application organization.

    Source observation
    presentation / backend roles
    Response observation
    physical deployment separate
    Evidence boundary
    monolithIsOneMandatoryBinaryOrProcess=false
  5. An SPA label does not determine backend topology

    SPA describes browser document and navigation behavior. The same frontend can talk to differently deployed backend layers or services; source HTML does not fully expose that layout.

    Source observation
    SPA document behavior
    Response observation
    backend topology not inferred
    Evidence boundary
    Frontend label != full architecture
  6. Add only known boundaries to the map

    This example establishes logical roles and in-process server calls. Cloud tiers, runtime processes and separate service counts require deployment observations.

    Source observation
    roles observed
    Response observation
    in-process calls declared
    Evidence boundary
    Physical layout requires evidence

IMPLEMENTATION · SECURITY CONTROL · VERIFICATION

Keep topology and responsibility ledgers separate

A local HTML builder and HTMLParser read produce source-text observations; API status/body are the example’s separate representation. These fields are not live browser DOM observations or packet captures. Record browser presentation, server endpoints/rendering, application service logic, and data ownership separately. Server calls to service/data are local in one process; no network diagram implies deployment-unit counts. The monolith multiple-project example describes packaging while three-tier guidance addresses physical placement. This lesson performs no framework rewrite, cloud deployment, or performance comparison.

Define method/target/status/media type/schema and the meaning of available results for the frontend/backend contract. A known public note returns title/version; an absent one returns selected404. Backend decisions own availability and the frontend presents results. Independent source HTML and JSON parsing/serialization support the contract, not access-control or deployment-isolation testing.

When the SPA title is plain text, assign the admitted string to the target node’s textContent rather than reparsing the API body with innerHTML. This choice is for an ordinary text node that needs no HTML content; it does not automatically protect URL, attribute or script contexts. In a browser regression, compare node.textContent with the validated title from the same request and verify that an ordinary 404 writes no success title. The lesson’s local HTML parser check does not measure this live DOM step.

Separate arrival, parsing, and UI commit

The scene first prepares sender target intent, changing server target knowledge only at request ARRIVE. During prepared responses the browser keeps Loading or empty knowledge. Response ARRIVE and local status/body/schema steps precede projected DOM text changes. API404 arrives as an ordinary Response, and the local guard prevents note-success commit. Reduced motion preserves the same states and controls.

The SSR source title, SPA Loading source text and API note shape/status are separate observations. Projected DOM text is the selected frontend contract’s expected outcome, not proof of display in a live browser. Establish the real UI result through response receipt, validation and DOM update for the same request.

NOW APPLY IT TO THE CASE

Which evidence separates the startup document from the later note request?

Duru opens the Atlas note card. In the server-rendered example, Tea note is present in the startup HTML. In the SPA example it contains Loading and the note is requested separately from an API. Opening the document does not establish success of that second request.

Which components contribute to the case response? Show where UI, service, platform and external-provider outcomes complete along their respective hops.

Open the related case file ↗

READ THE EXAMPLE TOGETHER

Public note source/representation/view ledger

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

Read the raw artifact and field explanations
{
  "roles": {
    "frontend": "Browser presentation",
    "backend": [
      "endpoint/render",
      "application service",
      "data owner"
    ],
    "serverCalls": "in-process, no fake wire",
    "selectedDeployment": "own local fixture, no cloud physical tiers",
    "monolithIsOneMandatoryBinaryOrProcess": false,
    "layersArePhysicalTiers": false
  },
  "ssr": {
    "target": "/server-note",
    "status": 200,
    "contentType": "text/html; charset=utf-8",
    "sourceHtml": "<!doctype html><html lang=\"en\"><body><h1 id=\"note\">Tea note</h1></body></html>",
    "sourceNoteText": "Tea note",
    "projectedDomText": "Tea note"
  },
  "spa": {
    "startupTarget": "/spa-note",
    "startupStatus": 200,
    "sourceHtml": "<!doctype html><html lang=\"en\"><body><h1 id=\"note\">Loading</h1></body></html>",
    "sourceNoteText": "Loading",
    "apiTarget": "/api/notes/tea",
    "apiStatus": 200,
    "apiContentType": "application/json",
    "body": "{\"id\":\"tea\",\"title\":\"Tea note\",\"version\":1}",
    "representation": {
      "id": "tea",
      "title": "Tea note",
      "version": 1
    },
    "projectedDomTextAfterValidation": "Tea note"
  },
  "apiFailure": {
    "startupStatus": 200,
    "apiTarget": "/api/notes/missing",
    "apiStatus": 404,
    "body": "{\"error\":\"not-found\"}",
    "fetchPromiseModel": "fulfilled Response with status404, not network rejection",
    "noteParsed": false,
    "projectedSuccessfulNoteCommitted": false,
    "projectedMessage": "Note unavailable"
  },
  "limits": {
    "native": "own HTML/JSON builders + independent Python HTMLParser only",
    "realHttpServerExecuted": false,
    "browserFetchExecuted": false,
    "browserDomExecuted": false,
    "frameworkExecuted": false
  },
  "selector": {
    "language": "XPath",
    "xml": "<audit><view apiStatus=\"404\" noteSuccessCommitted=\"false\"/></audit>",
    "xpath": "count(/audit/view[@apiStatus='404' and @noteSuccessCommitted='true'])",
    "expected": 0,
    "positiveFixtureXml": "<audit><view apiStatus=\"404\" noteSuccessCommitted=\"true\"/></audit>",
    "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
Logical responsibilities and physical deployment differ.
ssr/spa
Initial source HTML and API representations are separate stages.
apiFailure
Startup success differs from data-result failure.
limits/selector
Native source-parser versus authored DOM/promise projection scope.

This example compares SSR HTML and SPA JSON flows for a public note. Boxes show responsibilities and arrows show when information arrives; they are not a network capture. The title and error views are selected states rather than a complete framework model.

Two reality checks

Monolith, three-tier, and SPA are mutually exclusive architectures.

Deployment units, physical placement, and UI behavior are different axes that one application can combine.

Initial HTML200 or a fulfilled Fetch proves the note is ready in the DOM.

Startup, status, body/schema, and DOM commit are separate stages; HTTP404 can fulfill with a Response.

YOUR TURN

Work through this story.

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

SPA startup HTML is 200 but the API returns 404. Is successful-note DOM state committed?

  1. No; selected noteParsed=false and there is no successful-note commit.
  2. Yes; HTML 200 makes every subsequent API result successful.
Read the explained answer

No; selected noteParsed=false and there is no successful-note commit. — Startup success is not data availability; the fixture selects a Note unavailable message projection.

Do three backend roles prove three physical hosts?

Selected lesson artifact fields; teaching example

roles
{"frontend":"Browser presentation","backend":["endpoint/render","application service","data owner"],"serverCalls":"in-process, no fake wire","selectedDeployment":"own local fixture, no cloud physical tiers","monolithIsOneMandatoryBinaryOrProcess":false,"layersArePhysicalTiers":false}
  1. Yes; each layer is necessarily a network host.
  2. No; selected server calls are in-process.
Read the explained answer

No; selected server calls are in-process. — Endpoint/service/data-owner responsibilities may form logical layers; the selected local fixture measures no physical cloud tiers.

SSR source has Tea note and SPA source has Loading, while later projected DOM has Tea note. What does this teach, and which native-browser claim does it not establish?

Read the explained answer

SSR source carries initial note text; SPA applies a validated body to its view after a data request. The artifact uses owned builders/HTMLParser but has browserFetchExecuted/browserDomExecuted=false. The projection supports mechanism reasoning, not actual browser-rendering or framework SSR/hydration execution.

□ I separated source from later view state.

□ I did not count the projection as actual browser/framework execution.

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

Sources and scope