|
1 | 1 | --- |
2 | 2 | title: Architecture |
3 | | -description: How ObjectOS, the control plane, and the framework fit together. |
| 3 | +description: What you're actually running — for the engineer evaluating whether to bring this in. |
4 | 4 | --- |
5 | 5 |
|
6 | 6 | # Architecture |
7 | 7 |
|
8 | | -ObjectOS is one of three layers in the ObjectStack platform. Customers |
9 | | -usually deploy only ObjectOS; understanding the boundary between the |
10 | | -three layers makes deployment, security review, and incident response |
11 | | -easier. |
| 8 | +A practical view of what runs on your machines when you deploy |
| 9 | +ObjectOS, what data leaves your network, and what doesn't. |
12 | 10 |
|
13 | | -## The three layers |
| 11 | +## What you deploy |
| 12 | + |
| 13 | +One Node.js process per ObjectOS instance. That's it. |
14 | 14 |
|
15 | 15 | ```text |
16 | | -+--------------------------+ +--------------------------+ +--------------------------+ |
17 | | -| ObjectStack framework | | Control plane | | ObjectOS | |
18 | | -| (npm packages, source) | -> | (authors, publishes | -> | (customer-hosted | |
19 | | -| | | artifacts) | | runtime distribution) | |
20 | | -+--------------------------+ +--------------------------+ +--------------------------+ |
21 | | - runtime, plugins, projects, environments, executes artifacts, |
22 | | - drivers, services metadata authoring, owns runtime HTTP, |
23 | | - artifact storage business database |
| 16 | +┌─────────────────────────────────────────────────────┐ |
| 17 | +│ ObjectOS process │ |
| 18 | +│ ┌───────────────────────────────────────────────┐ │ |
| 19 | +│ │ HTTP dispatcher (/ · /api · /_studio …) │ │ |
| 20 | +│ ├───────────────────────────────────────────────┤ │ |
| 21 | +│ │ Per-project ObjectKernel (LRU cached) │ │ |
| 22 | +│ │ ├─ Auth (Better Auth) │ │ |
| 23 | +│ │ ├─ Security (RBAC + row-level + field) │ │ |
| 24 | +│ │ ├─ ObjectQL (data engine, generates SQL) │ │ |
| 25 | +│ │ ├─ REST API generator │ │ |
| 26 | +│ │ └─ Capabilities loaded per artifact │ │ |
| 27 | +│ │ (audit, storage, jobs, queue, AI …) │ │ |
| 28 | +│ └───────────────────────────────────────────────┘ │ |
| 29 | +└──────────┬──────────────────────────────────────────┘ |
| 30 | + │ |
| 31 | + ▼ |
| 32 | + Your business database |
| 33 | + (Postgres / MySQL / SQLite / Turso / MongoDB) |
24 | 34 | ``` |
25 | 35 |
|
26 | | -- **Framework** — the open-source `@objectstack/*` packages: kernel, |
27 | | - ObjectQL, plugins, drivers, services. Customers do not need to |
28 | | - understand or modify framework source to operate ObjectOS. |
29 | | -- **Control plane** — where applications are authored and where the |
30 | | - compiled `objectstack.json` artifact is published. May be the hosted |
31 | | - ObjectStack Cloud or a customer-operated control plane. |
32 | | -- **ObjectOS** — the runtime container customers deploy. It consumes |
33 | | - artifacts, builds a per-project kernel, talks to the customer-managed |
34 | | - business database, and serves application APIs and UI. |
| 36 | +It's a single statically-linked binary's worth of complexity. No |
| 37 | +sidecar, no Kafka, no separate cache layer required. Add those when you |
| 38 | +need them; don't pay for them on day one. |
| 39 | + |
| 40 | +## Where your data lives |
| 41 | + |
| 42 | +| Data | Lives in | Leaves your network? | |
| 43 | +|---|---|---| |
| 44 | +| Business records | Your database | **No** | |
| 45 | +| User accounts, sessions, OAuth tokens | Your database | **No** | |
| 46 | +| Audit log | Your database | **No** | |
| 47 | +| Settings, API keys, secrets | Your database / secret manager | **No** | |
| 48 | +| Uploaded files | Your disk or your S3/R2 bucket | **No** | |
| 49 | +| The compiled app definition (`objectstack.json`) | A file on disk or fetched from your control plane | Optional | |
| 50 | + |
| 51 | +ObjectOS does not call home. No telemetry. No license check. If you cut |
| 52 | +internet access entirely, it keeps running indefinitely. See |
| 53 | +[Air-gapped](/docs/deploy/air-gapped). |
35 | 54 |
|
36 | | -## What runs inside ObjectOS |
| 55 | +## How a request is served |
37 | 56 |
|
38 | 57 | ```text |
39 | | - +-------------------------------------+ |
40 | | - HTTP --> | HTTP dispatcher | |
41 | | - | /health · /api/v1/* · /api/v1/auth | |
42 | | - +-----------------+-------------------+ |
43 | | - | |
44 | | - +-----------------v-------------------+ |
45 | | - | KernelManager (LRU cache) | |
46 | | - | per-project ObjectKernel instances | |
47 | | - +-----------------+-------------------+ |
48 | | - | |
49 | | - +-----------------v-------------------+ |
50 | | - | Base plugins (always loaded) | |
51 | | - | ObjectQL · Security · Auth · i18n | |
52 | | - +-----------------+-------------------+ |
53 | | - | |
54 | | - +-----------------v-------------------+ |
55 | | - | Optional capabilities (per app) | |
56 | | - | audit · storage · jobs · queue · | |
57 | | - | realtime · feed · automation · | |
58 | | - | analytics · ai · settings | |
59 | | - +-------------------------------------+ |
| 58 | +1. Ingress / TLS termination (your load balancer) |
| 59 | +2. HTTP dispatcher (security headers, request id) |
| 60 | +3. Hostname → project resolution (cached, TTL configurable) |
| 61 | +4. Get or build per-project kernel from LRU |
| 62 | +5. AuthPlugin — session cookie, bearer token, or API key |
| 63 | +6. SecurityPlugin — RBAC + row-level + field-level checks |
| 64 | +7. Route handler — generated REST, declarative action, or custom |
| 65 | +8. Data driver — ObjectQL compiles to SQL / Mongo query |
| 66 | +9. Response with X-Request-Id propagated |
60 | 67 | ``` |
61 | 68 |
|
62 | | -Key properties: |
| 69 | +Steps 4-8 typically execute in < 5ms once the kernel is warm. |
63 | 70 |
|
64 | | -- One ObjectOS host can serve many projects. Each project gets its own |
65 | | - `ObjectKernel` instance, isolated database connection, and auth scope. |
66 | | -- Kernels are cached in an LRU (`OS_KERNEL_CACHE_SIZE`, default 32) with |
67 | | - an idle TTL (`OS_KERNEL_TTL_MS`, default 15 min) so cold-start cost is |
68 | | - amortised. |
69 | | -- Capabilities listed in the artifact's `requires` array are loaded |
70 | | - lazily from optional `@objectstack/*` packages bundled in the image. |
| 71 | +## The three layers (only matters if you're integrating) |
71 | 72 |
|
72 | | -## Boot modes |
| 73 | +Most customers deploy only **ObjectOS**. The other two layers exist if |
| 74 | +you want to know where the artifact comes from: |
73 | 75 |
|
74 | | -| Mode | When to use | Hostname resolution | |
| 76 | +| Layer | What it is | Where it runs | |
75 | 77 | |---|---|---| |
76 | | -| Cloud-connected (`OS_CLOUD_URL`) | Multi-project deployments, hosted control plane, dynamic project lifecycle | Resolved from the control plane's `/cloud/*` API | |
77 | | -| File-backed (`controlPlaneUrl: 'file'` + `OS_ARTIFACT_FILE`) | Single project, demo, air-gapped, smoke tests | Every hostname resolves to the same packaged project | |
| 78 | +| **Framework** (`@objectstack/*`) | Open-source kernel, ObjectQL, plugins, drivers | npm — pulled in at build time | |
| 79 | +| **Control plane** (optional) | Publishes compiled `objectstack.json` artifacts; you can use the hosted ObjectStack Cloud, run your own, or skip it entirely | Your CI, our cloud, or your laptop | |
| 80 | +| **ObjectOS** | The runtime you operate | **Your infrastructure** | |
78 | 81 |
|
79 | | -The ObjectOS app wrapper (`apps/objectos/objectstack.config.ts`) picks |
80 | | -the mode based on the presence of `OS_CLOUD_URL`. |
| 82 | +If you're shipping a single app, you don't need a control plane — |
| 83 | +compile `objectstack.config.ts → dist/objectstack.json` in your CI and |
| 84 | +ship the JSON in the image. If you're running an internal app |
| 85 | +marketplace with many tenants and apps, the control plane is where the |
| 86 | +catalog lives. |
81 | 87 |
|
82 | | -## Request lifecycle |
83 | | - |
84 | | -```text |
85 | | -1. Ingress / load balancer (TLS termination, X-Forwarded-For) |
86 | | -2. ObjectOS HTTP dispatcher (security headers, request id) |
87 | | -3. Hostname → environment (cached for OS_ENV_CACHE_TTL_MS) |
88 | | -4. KernelManager.acquire (build on miss, reuse on hit) |
89 | | -5. AuthPlugin (session/cookie or bearer/API key) |
90 | | -6. SecurityPlugin (RBAC + RLS + FLS) |
91 | | -7. Route handler (generated REST, custom action, auth route) |
92 | | -8. Driver (ObjectQL → SQL / Mongo / memory) |
93 | | -9. Response (X-Request-Id propagated) |
94 | | -``` |
95 | | - |
96 | | -## Data ownership |
| 88 | +## Boot modes |
97 | 89 |
|
98 | | -| Data | Where it lives | Owned by | |
| 90 | +| Mode | When | How | |
99 | 91 | |---|---|---| |
100 | | -| Compiled artifact (`objectstack.json`) | Control plane or local file | Application/release team | |
101 | | -| Business records (your domain data) | Customer-managed database | Customer | |
102 | | -| Identity (`sys_user`, `sys_session`, …) | Same database as business records | Customer | |
103 | | -| Settings (`sys_setting`) | Same database as business records | Customer | |
104 | | -| Secrets baseline (`OS_AUTH_SECRET`, OIDC client secret, DB creds) | Customer secret manager | Customer | |
105 | | -| Audit log (`sys_audit_log`) | Same database (when `audit` capability is enabled) | Customer | |
106 | | - |
107 | | -ObjectOS never copies business data back to the control plane. |
108 | | - |
109 | | -## Security boundary |
110 | | - |
111 | | -- ObjectOS only needs to make one outbound connection during operation |
112 | | - (to the control plane Artifact API) in cloud-connected mode, plus any |
113 | | - customer-configured integrations (SMTP, object storage, webhook |
114 | | - targets, identity providers). |
115 | | -- Air-gapped mode removes the control-plane call entirely. |
116 | | -- See [Production readiness](/docs/operate/production) for the |
117 | | - go-live checklist. |
| 92 | +| **Standalone** | Single app, dev, evaluation, air-gapped, most production deployments | `pnpm dev` or run `dist/objectstack.json` from disk | |
| 93 | +| **File-backed** | Production with externally-managed artifacts | Set `OS_ARTIFACT_FILE=/path/to/objectstack.json` | |
| 94 | +| **Cloud-connected** | Multi-tenant / multi-app deployments fed by a control plane | Set `OS_CLOUD_URL` + `OS_CLOUD_API_KEY` | |
| 95 | + |
| 96 | +Mode is auto-detected from environment variables. |
| 97 | + |
| 98 | +## Performance characteristics |
| 99 | + |
| 100 | +| Metric | Number | |
| 101 | +|---|---| |
| 102 | +| Cold start (process up, ready for traffic) | ~1 second | |
| 103 | +| Per-kernel warmup (first request to a project) | 50-300ms depending on capabilities | |
| 104 | +| Warm request latency (CRUD via REST) | typically < 10ms + database latency | |
| 105 | +| Memory footprint | ~150MB base; ~10-30MB per active project kernel | |
| 106 | +| Concurrent projects per instance | Limited by `OS_KERNEL_CACHE_SIZE` (default 32) | |
| 107 | + |
| 108 | +## Why this shape |
| 109 | + |
| 110 | +- **One Node process, no sidecars** → fits in a `docker run`, fits in a |
| 111 | + systemd unit, fits in a Lambda-like environment. |
| 112 | +- **Per-project kernel, LRU cached** → one instance can serve many |
| 113 | + small apps without paying the warmup cost on every request. |
| 114 | +- **Generated APIs on top of declared metadata** → there's no codegen |
| 115 | + step in your CI, no client SDK to publish; the API matches your data |
| 116 | + model by construction. |
| 117 | +- **All capabilities are optional plugins** → image size scales with |
| 118 | + what you actually use. |
| 119 | + |
| 120 | +## Where to go next |
| 121 | + |
| 122 | +- [Production Readiness](/docs/operate/production) — checklist before |
| 123 | + exposing it to real traffic. |
| 124 | +- [Runtime Configuration](/docs/configure/runtime) — wiring databases, |
| 125 | + caches, and secrets. |
| 126 | +- [Runtime Capabilities](/docs/reference/runtime-capabilities) — |
| 127 | + which optional packages exist and what they enable. |
0 commit comments