Skip to main content
Your Cloud key is your database. Threads, apps, records, blobs, state, grants, approvals, audit, and runs persist in Vendo Cloud’s Postgres.

The store slot fills itself

createVendo picks the store at composition time. With VENDO_API_KEY set and no store passed, the slot takes the hosted store.
app/api/vendo/[...vendo]/route.ts
The adapter never reads the environment. The composition does, then hands the adapter a key and a base URL. Your boot log says which one won:
vendo ready
Tenancy is resolved server-side from the key’s organization, on every call. Nothing in your process picks a tenant.

What lands where

The hosted store speaks the same wire your process would speak to a local database, one hop shorter. Blobs ride the same store unless you pass a files adapter. One adapter serves both writes and the erase cascade, so rows and objects can never drift apart. ensureSchema() is a no-op against Vendo Cloud. The service owns its own migrations.

What the store refuses

The store refuses three things outright. Each one shows up in a log rather than as a silent no-op.
Writing vendo_audit with an id that already exists fails with conflict. Deleting an audit row is refused with blocked.The erase API below is the only sanctioned way to remove one.
vendo_apps, vendo_grants, and vendo_threads reject a same-id write that moves a row to a different subject.To transfer ownership, delete the row and re-seed it under the new subject.
The hosted store has no secrets surface, by construction. Secret values resolve from your process environment first, and Vendo Cloud’s secrets provider answers only for names the environment leaves unset.Nothing sends a secret value to the console as store data.

Erasing a user

Erasure is the deletion path for right-to-erasure requests, for tearing down a test app, and for purging old runs. It cascades across every store table, and which call you make depends on which store this deployment composed. A LOCAL store — the default, or your own Postgres — runs the SQL cascade through eraseStore, which takes the files adapter so rows and objects go together:
The HOSTED store carries its own erase door with the same two methods and no files — the console cascades its own storage server-side. eraseStore cannot be handed that store: it throws Unknown VendoStore handle before any request goes out.
Either way the call returns per-table deleted counts, so you can log the cascade or assert on it. Erasing a user has the one branch that serves both postures — the branch the Maple demo ships.
Against Vendo Cloud, the erase door needs an admin-scoped VENDO_API_KEY. A runtime-scoped key is refused with HTTP 403 and the blocked code before the request body is read.Every key defaults to the runtime scope. Mint an admin key from your project’s Keys page in the console, where Admin is a deliberate second click.

Racing writers

Two ticks, two retries, or two agent runs can land on the same record. The collection handle carries compare-and-set primitives for that case.
claim returns true for the single caller whose read of expected still matched. insertIfAbsent and compareAndSwap return null when another caller won. Both are optional on the handle, which is why the calls above are guarded. Your own collections expose them; Vendo’s internal tables vary.

Where to go next

Vendo Cloud

What the key covers, what it costs, and how to mint a scoped one.vnd_ + 40 hex

Auth

The subject every row above is scoped to, and where it comes from.principal.subject

Deploying

The eight checks that have to pass before your users arrive.npx vendo doctor