Cloud or your own perimeter
One codebase, two deployments.
Cloud - run by us, updated by us, billed by usage.
On-prem - inside your network, on your hardware, on your own schedule. Same applications, same processes, same AI harness - and your own models, since a self-hosted checkpoint or any OpenAI-compatible endpoint connects as an ordinary provider. See Privacy and on-prem for the sizing.
There is no reduced on-prem edition. What differs is who operates it.
Services, not a monolith
The system is a set of containerised services, each written in the language its job actually needs:
| Tier | Job |
|---|---|
| Control plane | The API surface, authoring, orchestration control, the AI harness |
| Query engine | Compiled query planning and execution over the data lake - Go, with a Rust extract executor over DuckDB |
| Ledger | Double-entry postings and balances, as its own service |
| Process service | The BPM engine - JVM, schema-per-organisation |
| Collaboration server | Live document sessions for spreadsheets and co-editing |
| Object storage | S3-compatible storage for Parquet, files and artifacts |
| Relational store | PostgreSQL - schema-per-organisation |
| Cache and queues | Redis |
| Identity | Session and OAuth2 services in front of everything |
| Reverse proxy | One ingress |
The split is what lets the analytical tier be written for throughput, the process tier be a mature JVM engine, and the collaborative tier hold live document state, without any of the three constraining the others.
See Data engine and Processes under the hood for what runs inside two of those tiers.
How updates are built
A release is a commit, not whatever images happen to be current.
- On every push to the main branch, CI builds one image per service and pushes it tagged with the commit.
- A final job verifies the whole set exists before the run counts as a release. A partial build is not a release.
- The commit tag is immutable. There is a moving convenience tag as well, and production is never allowed to use it, because a per-service moving tag cannot tell you the fleet agrees on one commit.
- Deployment pulls that verified set and refuses to start if any image for that commit is missing.
- Every service reports the commit it was built from, so "what is production running" is a question with an answer.
- Database migrations run on their own path at service start, so a deploy that spans several commits carries whatever accumulated between them.
See Deployment.
Scaling
Because the tiers are separate, they are sized separately - which is the whole point of the split.
Vertically, where memory and cores buy the most: the query engine and the extract executor are where a bigger machine turns directly into more concurrent analysis over more data, and the relational store is the other tier that rewards a larger box.
Horizontally, where state is not in the process: the request-serving tiers hold their state in PostgreSQL, Redis and the object store rather than in memory, so adding instances behind the proxy is configuration, not redesign. The same is true of orchestration workers, which is how a backlog of process work is absorbed.
One exception: the collaboration server holds live document sessions in memory, so it scales with session affinity instead of round-robin.
And the storage tier scales by not being in the database. Analytical data is columnar files in object storage, read directly by the engine, so growth in data volume is storage cost and not a database migration. See Sources and storage.
What is in this block
- Integrations - the connector registry, building your own, and the MCP endpoint other tools reach in through.
- Access and isolation - single sign-on, roles and grants, row-level rules, column masking, and how one organisation is kept out of another.
- Environments - deployment topology and licensing.
- Versions and the built-in git - what a version of an application is, and the real git transport underneath it.
- Audit - what is recorded, for both kinds of actor.