Skip to content

docs: add Multiple Applications on One Cluster guide#586

Open
BboyAkers wants to merge 5 commits into
mainfrom
docs/multiple-applications-one-cluster
Open

docs: add Multiple Applications on One Cluster guide#586
BboyAkers wants to merge 5 commits into
mainfrom
docs/multiple-applications-one-cluster

Conversation

@BboyAkers

Copy link
Copy Markdown
Member

Summary

Adds a new developer guide, Multiple Applications on One Cluster, covering how to run multiple applications on a single Harper cluster:

  • Applications as components on a shared cluster
  • Structuring each application with config.yaml
  • Keeping applications separate along three boundaries: routes, data, and roles
  • Registering applications declaratively (harperdb-config.yaml) and imperatively (CLI)
  • Deploying across the cluster with replicated=true
  • Guidance on when to co-locate vs. use separate clusters

Written in the platform's technical-documentation tone, consistent with the sibling harper-applications-in-depth.mdx guide.

🤖 Generated with Claude Code

Add a guide covering how to run multiple applications on a single Harper
cluster: how components coexist, how to isolate them via routes, data, and
roles, and how to deploy across every node.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@BboyAkers
BboyAkers requested a review from a team as a code owner July 15, 2026 15:00

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds a new documentation guide on running multiple applications on a single Harper cluster. The reviewer feedback correctly identifies several naming errors in the documentation, specifically pointing out that the configuration file should be named 'harper-config.yaml' instead of 'harperdb-config.yaml', and that the CLI command is 'harper' rather than 'harperdb'. Additionally, the reviewer suggested using a Docusaurus note admonition instead of a standard markdown blockquote for consistency.

Comment thread learn/developers/multiple-applications.mdx Outdated
Comment thread learn/developers/multiple-applications.mdx Outdated
Comment thread learn/developers/multiple-applications.mdx Outdated
Comment thread learn/developers/multiple-applications.mdx Outdated
Comment thread learn/developers/multiple-applications.mdx Outdated
Comment thread learn/developers/multiple-applications.mdx Outdated
Comment thread learn/developers/multiple-applications.mdx Outdated
BboyAkers and others added 2 commits July 15, 2026 11:04
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Rename config file references to harper-config.yaml (was harperdb-config.yaml)
- Use the harper CLI consistently (was harperdb)
- Convert the restart note to a :::note admonition
- Fix broken doc links to resolve to /reference/v5/ targets

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions
github-actions Bot temporarily deployed to pr-586 July 15, 2026 15:22 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-586

This preview will update automatically when you push new commits.

@kriszyp kriszyp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this together — the mechanics that are here (config.yaml precedence, ports, deploy_component replicated=true) are accurate, and the broken cross-references from the first pass are fixed.

Requesting changes on scope/completeness, though — for a "multiple applications on one cluster" guide, the routing story is the crux and it's currently thin:

Significant — routing is incomplete. The guide only covers static assets / Fastify. It doesn't explain middleware routing by URL path, which is the primary mechanism for fronting multiple apps on one instance (how a request path maps to a given application). That should be the backbone of this guide, not an aside.

Significant — virtual hosts are missing. Hostname-based routing (virtual hosts) is arguably the feature for hosting multiple apps on one cluster — routing by host, not just path. A multi-app guide that omits it leaves out the main pattern users will reach for.

Significant — module loader context isolation. When several apps run in one instance, how their module loader contexts are isolated (or shared) is a real correctness/operational concern and belongs in this guide — at minimum a section explaining the isolation model so users understand what is and isn't shared between co-located apps.

Happy to point at the canonical references for each of these if that helps. The foundation is good; it just needs the routing + isolation story filled in before it's the guide people should follow for this topic.

— review via KrAIs (Claude) on Kris's behalf

Address maintainer review requesting fuller routing and isolation coverage:

- Make routing the backbone: new "Routing requests to each application"
  section covering path-based routing (urlPath), the server.http()
  middleware chain, and host-based routing via request.host
- Add "What co-located applications share" section documenting the module
  loader context isolation model (isolated module caches, shared
  process-wide data/APIs, shared process lifecycle)
- Note SNI certificate configuration for serving multiple domains

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@BboyAkers

Copy link
Copy Markdown
Member Author

Thanks @kriszyp — good call on scope. Pushed changes addressing all three:

  • Middleware routing is now the backbone. New top-level Routing requests to each application section with three parts: path-based routing (urlPath, including the ././ component-name prepend and the deploy_component urlPath override), the server.http() middleware chain (next(request) / runFirst), and host-based routing.
  • Host-based routing. Documented via a server.http() handler branching on request.host (routing admin.example.com vs listings.example.com), plus a pointer to SNI (tls array with per-domain host) for multi-domain certs. Note: I couldn't find a first-class virtual host config feature in the current docs, so I documented the middleware pattern using the documented request.host primitive. If there's a canonical virtual-host reference I missed, point me at it and I'll rewrite this section around it.
  • Module loader context isolation. New What co-located applications share section: module contexts isolated per app (Node VM loader / distinct module caches), while tables/databases and the Harper APIs are the same live, process-wide objects — and the process/restart lifecycle is shared. Sourced from the JavaScript Environment reference.

Verified with a full docusaurus build (no broken links/anchors) and Prettier.

@github-actions
github-actions Bot temporarily deployed to pr-586 July 15, 2026 18:30 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-586

This preview will update automatically when you push new commits.

@kriszyp kriszyp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes, but narrower than the automated review suggested — checked the two API-shape claims against Harper's actual Request implementation before posting, and they don't hold up:

  • request.host and request.pathname are real, documented Harper Request properties (server/serverHelpers/Request.ts), not something that needs request.headers.get(...) instead — no change needed there.
  • Marking the handlers async isn't required for crash-safety either: requestHandler in server/http.ts already wraps the whole chain call in a try/catch (await httpChain[port](request)), which catches a synchronous throw from a non-async middleware just as reliably as an async one.

The one thing genuinely worth fixing: the first example's prose says "dispatch on a custom header" but the code shows a path-prefix check (request.pathname.startsWith('/listings')) — text and code don't match each other. Worth making the example match the text (a header check, since that's the case path-prefix routing doesn't already cover) so the doc isn't demonstrating the wrong tool for the job it describes. Not a correctness or performance bug, just an internal consistency fix.

The middleware-chain example described dispatching on a custom header but
showed a path-prefix check — a case path-based routing already covers.
Switch the example to a custom-header check so it demonstrates what the
surrounding text actually recommends the chain for.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@BboyAkers

Copy link
Copy Markdown
Member Author

Thanks for checking the API shapes against the source, @kriszyp — agreed on all counts (request.host/request.pathname are real, and the chain's try/catch makes async unnecessary), so I left those as-is.

Fixed the one genuine issue: the middleware-chain example now dispatches on a custom header (x-app-target) to match its prose, instead of showing a path-prefix check that path-based routing already covers.

@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-586

This preview will update automatically when you push new commits.

@kriszyp kriszyp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the hostname-routing section. One significant correction is still needed: the current example manually branches on request.host, but Harper 5.2 has first-class virtual-host routing.

Components can declare host in config.yaml; the scoped server API automatically carries that value into the component’s HTTP, WebSocket, and upgrade registrations. Custom code can register the same routed chain directly with server.http(handler, { host: "admin.example.com" }). Harper then matches the request Host header and selects the corresponding isolated middleware chain.

Please make that declarative host configuration the primary application-routing pattern, show the direct { host } option as the programmatic equivalent, and reserve branching on request.host for genuinely custom dispatch. The SNI material should remain separate: SNI selects the certificate, while host selects the application middleware chain.

I opened Document middleware host and path routing (#595) to add the missing canonical references for both host and urlPath; this guide can link to those sections once it lands.

— review via KrAIs (GPT-5) on Kris’s behalf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants