Control plane / data plane / billing plane — architecture
A one-page map of the Kucatoo hosted stack. Three planes, two external services, and the arrows that connect them.
flowchart TB
subgraph users["People"]
cust["Customer<br/>(Clerk sign-in)"]
op["Operator — you"]
end
subgraph cp["CONTROL PLANE — kucatoo-code<br/>(coder.kucatoo.ai · kucatoo-code.fly.dev)"]
direction TB
web["Web app (Flask harness)"]
console["Sites tab (operator) · My instances (customer)<br/>create / upgrade / destroy / reset"]
hook["/api/hosting/hook<br/>(grant · change · revoke)"]
pay["pay_hub.py"]
fly["fly_client.py"]
clerk["Clerk JWT auth"]
end
subgraph billing["BILLING PLANE — kucatoo-pay<br/>(pay.kucatoo.ai)"]
hub["FastAPI hub<br/>entitlements · checkout · portal · webhooks"]
end
subgraph data["DATA PLANE — customer VMs"]
vm["kucatoo-k-…<br/>one VM per subscription<br/>(slim or full image)"]
end
subgraph ext["External services"]
stripe["Stripe"]
flyio["fly.io (machines · volumes · IP · DNS)"]
end
cust -->|"HTTPS — use the product"| vm
cust -->|"HTTPS — manage instances"| web
op -->|"HTTPS — operate"| web
web --> clerk
web -->|"checkout · portal · plan change"| pay
pay -->|"S2S (bearer key)"| hub
hub -->|"checkout · portal · subscription"| stripe
stripe -->|"webhooks"| hub
hub -->|"provision hook: grant / change / revoke"| hook
hook --> web
web -->|"provision · reshape · destroy"| fly
fly -->|"Machines API"| flyio
flyio -->|"runs"| vm
Reading it
| # | Arrow | Meaning |
|---|---|---|
| 1 | Customer → VM | The customer uses their own VM directly (chat, Files tab, etc.). |
| 2 | Customer / operator → control plane | The console: operator sees the Sites tab; a customer sees only "My instances". |
| 3 | Control plane → hub | pay_hub.py brokers Stripe checkout/portal/plan-change server-to-server. |
| 4 | Stripe ↔ hub | The hub talks to Stripe; Stripe calls back with webhooks. |
| 5 | Hub → control plane | The provision hook (grant/change/revoke) tells the control plane to build/reshape/suspend a VM. |
| 6 | Control plane → fly.io | fly_client.py actually creates/updates/destroys the machines. |
| 7 | fly.io → VM | The data-plane VMs run on fly.io. |
The three planes, one line each
- Control plane (
kucatoo-code) — the manager: one per operator, holds the console, the provision hooks, and the S2S billing broker.coder.kucatoo.ai. - Billing plane (
kucatoo-pay) — the cashier: Stripe checkout/portal, entitlements, webhooks. One per operator. - Data plane (
kucatoo-k-*) — the workers: one VM per customer subscription, running the actual product. Many, created on demand.
Two deploy paths (why "deploy" is two jobs)
- Control plane —
flyctl deploy -a kucatoo-code(remote build). - Data plane — rebuild + push
kucatoo-code:slim/:full, pin the digests inhosting_tiers.py, then update each VM's machine image.