The framework defines the shape of an app; the platform is the substrate it runs on — the way Heroku stood beside the twelve factors. An author ships releases: immutable, content-addressed artifacts. The platform places them on instances, routes to them through a mesh, hibernates them when idle, and wakes them on the request that needs them. Apps from many authors run side by side on the same fleet, sharing the same blind infrastructure.
The whole self-hosting story is one sentence: a deployment is a bucket, N hosts running one binary, and DNS. Keeping it one sentence is a design constraint on everything else.
There is no control-plane server to stand up, and none to be locked out of. All durable platform state — apps, releases, channels, instance records, leases — lives in an object-store bucket; hosts converge by watching it, and a burned-down box is replaced by pointing a fresh one at the bucket. The platform makes about itself the promise its instances already make: the box is disposable, the bucket is not. It is entirely open and trivially self-hostable, and two of its first three deployments are self-hosted — so anything the flagship needs that a self-hoster can't have is a design error, caught immediately.
Ship, canary, promote
The dev pipeline is the prod pipeline, exercised on every push.
carlos ship uploads a release under its content hash. A channel is a per-app pointer to a release — stable, beta, and ephemeral canary/* channels — and advancing one is a single pointer write. Instances subscribe to a channel and roll onto new releases at their next natural boundary: wake from hibernation, or a drain-and-restart sweep. Rollback is the same operation backwards.
Every branch gets a canary URL
carlos canary from a worktree builds, ships, creates a channel, spawns one instance bound to sandbox glue, and returns its URL — in seconds, not minutes. A dev environment is not a separate system; it is a channel with one subscriber.
Promotion never rebuilds
carlos promote points a wider channel at the same hash: canary → beta → stable. Every environment running release abc123 runs byte-identical code. What you tested is what ships, because it is the same bytes.
Rollback is a pointer move
A bad release hits gradually — instances adopt on wake — and pointing the channel back at the previous hash stops the bleed. Additive-only migrations mean old data stays readable under new code and new data survives the trip back.
Static sites ride the same channels
A static release is a content-addressed file tree the edge serves directly — no process, nothing to hibernate. Same canary URLs per branch, same promotion, same rollback. This page ships that way.
Sleeping is the default state
Most software is used a few hours a week. The platform bills like it.
An idle instance hibernates, and its database parks to object storage: a parked app is a few objects in a bucket — no process, no memory, no host doing anything on its behalf. The next request wakes it, on whichever eligible host answers first. Availability is continuous even when execution isn't.
- Per-instance databases, continuously replicated. Every instance owns its own database, and it streams to the bucket from the first byte. Losing a host costs a restart, not a history: its leases expire and the instances wake elsewhere from their last parked state.
- Scheduling is deliberately dumb. No bin-packing optimizer — hibernation makes placement mistakes cheap. A badly-placed instance parks and wakes somewhere better next time.
- Scale is a declaration, not a rewrite. Parked → embedded SQLite → replicated → an attached server database (one per instance, inside the app's trust domain, never multi-tenant) → a dedicated pool. An app moves along that curve by changing its manifest, not its architecture.
Placement you can point at
Residency is enforced where the instance wakes, not promised in a policy PDF.
Choose where data lives
An app — or a single instance, because one customer may demand EU while another doesn't care — declares residency: eu. A host outside the region will not claim the lease, so there is no code path where the instance runs elsewhere "just this once during a failover": no eligible host up means the wake fails loudly. Parked data, streams, and blobs rest in region-scoped buckets. Residency covers rest as well as execution.
Your own hardware, same platform
Apps that hold real personal or payment data — not everything is end-to-end encrypted — can reserve hosts: their instances, parked data, and wake path only ever touch that pool, optionally with its own bucket, while still riding the shared edge, channels, CLI, and services.
Shared services: blind or seeing, never both
Nothing that sees may store.
Every shared service carries a declared class, visible in the manifest of every app that consumes it. Blind services may hold data, but only data they cannot read: the object store holds parked databases and blobs but no plaintext of E2EE apps; the vault holds sealed blobs whose keys live elsewhere; the push relay holds device tokens and timing but never notification content; the OAuth relay passes tokens through sealed to the requesting instance, never retaining them. What makes them blind is falsifiable the CARLOS way — publish their state and see what leaks.
Seeing services process plaintext — a URL unfurler, a PDF renderer, outbound mail — and are therefore forbidden to hold it. Not by promise: the platform grants a seeing service no database binding, no bucket write access, no persistent volume. Statelessness is imposed by construction. One honest caveat the mail service carries with it: the underlying email provider retains delivery metadata — bounces, complaints, suppressions — scoped per tenant.
Supply-chain honesty
The scary step in any pipeline is the pointer that says "this is stable now."
- Channel pointers are signed. A host agent rolls instances onto a release only when the pointer advancing the channel carries a valid signature — a bucket write alone is not a deployment.
- Releases bake before stable adopts them. A release must sit on its channel for 72 hours before stable instances roll onto it — time for a poisoned artifact to be noticed while its blast radius is still the people who opted in.
- Rollback never bakes. Pointing back at a hash that already served traffic takes effect immediately. The waiting period protects against new code, and going backwards is never new code.
Every release records its build attestation — commit and builder — under its hash, and every platform change ships through the platform itself: worktree, canary channel, a miniature canary deployment, a headless-browser gate that fails on any console error. The release machinery is tested by being the only way anything ships, including itself.
Three deployments, one platform
The Open promise is proven from day one, because the first two production users are self-hosters.
Tito
Ticketing for conferences and events, running its own self-hosted deployment on its own account. Self-hosted use-case number one, and the platform's first proving ground.
Eleven
The encrypted messenger, on its own deployment — and the code quarry: the platform's edge, host agent, channels, and mergeable stores were extracted from Eleven's proven machinery.
The flagship cloud
The shared multi-tenant deployment, operated by the CARLOS authors, hosting Keymail, Woodstar, Slopbox, and Kass — the first four customers. Same open platform, differing from the self-hosted two in variables, never in shape.
Apps live at <sqid>.oncarlos.com — an address that never encodes region or host, so relocation and placement stay invisible to it. Custom domains ride on top as aliases.
Where it actually stands
Fewer claims, all of them checkable — including this one.
The platform is young. It was extracted from Eleven and titogo — systems that kept rebuilding the same deployment shape until it was obviously one thing — and its first production tenant, Kass, migrated onto it on 2026-08-01. Everything above describes the design being built and proven, not a mature product with years of scar tissue. If that honesty reads oddly on a homepage — good. It is the same trade the framework makes: the platform holds itself to the promises it hosts, and a promise you can't check yet is stated as exactly that.