ADR-0001: Hosted vs Self-Hosted Topology
Architecture decision: one codebase for the hosted and the self-hosted Gateway, and how the two differ.
Mirrored from
adr/ADR-0001-hosted-vs-self-hosted-topology.mdin the EveryApp repository, where it is edited.Read with care: Historical (2026-03-02). Section 6's single-tenant hosted Workers were overruled on 2026-10-16: first-party apps share one Worker per app, third-party apps get one Worker per organization on Workers for Platforms (/docs/agent/repo/security-model and /docs/agent/repo/hosted-vision).
- Status: Accepted, in part superseded. The hosted topology below (one Worker per organization for every app) was reversed on 2026-10-16: first-party apps share one Worker per app, third-party apps run one Worker per organization in a dispatch namespace. The rulings and the invariants that bind the code are in
docs/hosted-vision.md; the self-host side of this record still holds. - Date: 2026-03-02 (note added 2026-10-24)
Context
We are building a hosted version of the Every App Gateway, while keeping self-hosting as a core product path. The current gateway and CLI assumptions are strongly single-tenant/global, and app deploy workflows assume the gateway and apps share a Cloudflare account.
Key constraints for the near term:
- Product is still pre-launch/POC and can tolerate breaking changes.
- We need a practical path to multi-tenant organizations.
- We want to avoid unnecessary codebase/release complexity early.
Decision
- Use a single repository and single gateway application codebase, with runtime mode separation:
self_hostedmodehostedmode
- Use organization-based multi-tenancy in hosted mode.
- Keep hosted and self-hosted differences policy-driven (feature/capability flags), not forked app logic.
- Control-plane trust model is mode-specific:
self_hosted: Cloudflare account token is the internal control-plane root-of-trust.hosted: Cloudflare account ownership checks are not a valid tenant authorization boundary.
- Control-plane trust model is mode-specific:
- Use an open-core boundary:
- Open: gateway core, auth/session flows, organization model, app runtime APIs.
- Potentially private later: hosted-only control-plane operations (billing, anti-abuse policies, internal operational tooling).
- Hosted provider credentials are platform-managed for v1:
- Gateway uses a platform-owned provider API key for AI proxying.
- Customer apps and users never receive provider API keys.
- BYO provider keys are explicitly deferred.
- Hosted app worker deployments are single-tenant for v1:
- Each deployed app worker instance is scoped to one organization.
- Multi-tenant app worker runtime support is deferred.
Rationale
- Avoids repository drift and duplicated maintenance.
- Allows faster POC iteration with one deployable gateway artifact.
- Preserves future flexibility for hosted-private features without committing to a hard split now.
Consequences
Positive:
- Faster implementation and lower maintenance overhead.
- Cleaner migration path from current global model.
Negative:
- Need disciplined boundaries to prevent hosted-only logic from leaking into self-hosted paths.
- Requires clear capability toggles and tests for both modes.
- Internal API behavior must be explicitly fail-closed by mode (no implicit fallback to self-hosted semantics).
Follow-ups
- Define and document mode/capability flags.
- Keep control-plane integrations behind explicit interfaces.
- Long-term: gateway will expose an OAuth provider so CLI and other clients can authenticate through gateway-managed identity/org context instead of relying on Cloudflare account tokens.
- Revisit this ADR after hosted GA usage patterns are known.
Hosted Install
Operator runbook (hosted tier, post-launch): the hosted Gateway (app.everyapp.com): install, shared first-party apps, the gated third-party deploy API and its deploy keys, launch checks.
ADR-0003: Self-Hosted Operator Authority Is Cloudflare Account Access
Architecture decision: on a self-hosted Gateway, operator authority is Cloudflare account access; there is no deploy API.