features · compute & data

Everything that runs, and the data behind it.

WASI functions as the compute primitive, a GraphQL API generated from your database, host-enforced multi-tenancy, and containers & microVMs for heavier cargo.

Everything is pre-1.0. Where a capability's live validation is still in flight, it's marked: live seam beta in progress
01 / FUNCTIONS

Everything that runs is a function.

The function model
One primitive, many doors
A function is a portable WASI 0.2 component. Reach the same component as a route handler, invoke it by name, put it on a cron, or drive it from a queue: a different door, one sandbox.
function
Invoke by name
Top-level functions carry their own version line (function deploy / alias / rollback) and invoke sync or async: durable, idempotency-keyed, and dead-lettered on failure.
function invoke
Function mesh
A site handler can call sibling functions in-process through a deny-by-default invoke_targets allowlist: the caller's bearer is forwarded unchanged, the callee quota-admitted and depth-capped. A mesh orchestrator with no network hop.
invoke_targets
Streaming invoke
Consume a sibling function's response as a stream (status and headers up front, the body pulled incrementally through an incoming-response resource) so a large or @defer-style result is never buffered whole in host memory.
invoke --stream
Compose components
Author resolvers and middleware as separate WIT-typed components and fuse them into one linked component in-process with boatramp compose (no network hop, checked at compile time), then deploy the single .wasm.
compose
Event triggers
Fire a function from a signature-verified HMAC webhook, or a blob-change event (the changed key arrives as the invocation body) via the backend's native notifications.
webhook · blob
Multi-language
Author in Rust, JavaScript (jco), or Python (componentize-py); scaffold, build, and test locally with function init · build · test · dev.
rust · js · py
Metering & quotas
Every invocation is metered and exported to Prometheus, with fail-closed rate-limit and concurrency quotas.
function usage
Workflows
Chain functions into a durable DAG: fan-out, barrier fan-in, per-step retries, and saga compensation on failure. Runs survive restarts.
workflow
Long-running jobs
A durable background job (an LLM generation, an --async batch, a workflow step, a cron or queue trigger) runs on a separate async lane (a larger wall-clock ceiling on its own concurrency budget), so it runs to completion without ever starving live site traffic. The drain leases each invocation and redrives it if a node dies mid-run.
async_max_timeout_ms
Streaming response lane
A long-lived streaming handler (SSE, chunked output, agent token streaming) runs on its own engine lane with a dedicated concurrency budget and a large wall-clock (defaults 15 min, 64 concurrent), isolated from both the fast request pool and the durable async drain, so a burst of streams starves neither.
streaming = true
Data bindings
Per-site SQL
A real libsql database per site: an embedded file on one node, or a sqld namespace across a cluster.
sql
Bring your own SQL live seam
Point the sql binding at your own Postgres or MySQL (Neon, Supabase, PlanetScale): opened by name, read-only enforceable, the URL kept in a secret. Guest code is unchanged.
sql-postgres · sql-mysql
Managed database
Source the sql binding from a Postgres/MySQL workload boatramp runs: it resolves the live endpoint so the binding follows the database across restarts, and can fully manage the credential (generate, seal with the [secrets] envelope, and inject) so the operator sets no DB secret at all.
compute: db
Declarative databases
Declare a per-tenant Postgres or MySQL right in the apply manifest: boatramp provisions the workload, mints and seals the credential, and follows it across restarts, with no secret in the manifest.
databases: [ … ]
Schema migrations
An owner-gated migration surface (each step a wasm function, a SQL script, or an allowlisted extension) with boatramp owning ordering, a durable ledger, idempotency, and a baseline to adopt an existing database. Postgres, MySQL, and embedded libsql.
project migrate
Named SQL bindings
Grant a handler named databases: sql:product for the RLS-enforced product role, sql:privileged for a separate cross-tenant role (or sql:* for all), each its own connection and credential, capped by the site's allow_imports. Least-privilege that makes Postgres FORCE ROW LEVEL SECURITY real.
sql:name · sql:*
Per-tenant databases
A managed sql binding isolates each tenant into its own database (a shared server with a database + login role per tenant, or a dedicated server per tenant) each with its own sealed credential, so one tenant's role can never reach another's. Or set rls_session and boatramp injects the request's tenant into the SQL session for your own row-level-security policies.
tenant · rls_session
Typed query builder
Build queries as a typed tree instead of SQL strings: joins, GROUP BY/HAVING, IN/BETWEEN/LIKE, upserts, RETURNING, and JSON key-paths, all compiled to parameterized SQL for the backend's dialect (a closed function enum, every value bound, so a guest can't construct an injection), with an optional row-scope folded into every write for sub-tenant isolation.
handlers/orm
Vector search experimental
Nearest-neighbour search from the typed query builder: cosine (<=>) or L2 (<->) distance over a bound ?::vector in a select list or ORDER BY, on Postgres + pgvector. The metric is a compiler constant and the vector binds as a parameter, so nothing is interpolated.
pgvector
KV · blob · queue
Per-site key/value, blob store, and durable messaging bindings, granted to the function.
kv · blobstore · messaging
Send email
A function calls send(message) and the host delivers it through an operator-configured SMTP profile: credentials host-held (never reaching the guest), a spoof-proof From, and optional durable retry with a dead-letter.
handlers/email
Message-queue fabric
A project-scoped topic bus (bus:<topic>) carries events between a project's sites and functions. Subscribe as a competing-consumer work queue (lease, redelivery, dead-letter after max_attempts) or a named durable consumer group: fan-out where every group sees every message on its own cursor. A verified inbound webhook can publish straight onto the bus.
bus · consumer groups
Streams (SSE / WebSocket)
Fan messaging topics out to connected clients over Server-Sent Events or WebSocket.
streams
The sandbox
Deny-by-default imports
A function receives only the capabilities the site grants; anything else is refused at activation.
imports
Portable capabilities
A function declares the capability features it requires; the host advertises what it implements (boatramp capabilities, each tagged stable or experimental) and activation fails loud, naming any missing feature. boatramp capabilities check gates a component in CI against the boatramp version it targets.
capabilities check
02 / GRAPHQL

GraphQL, understood at the edge.

GraphQL from your database
Generate a read + write GraphQL API from a managed database with no resolver code: boatramp introspects the schema and compiles each query to one parameterized SQL statement. Relationships become correlated JSON subqueries, so a nested query is one round-trip with no N+1.
graphql.data
Deny-by-default, tenant-isolated
Only the tables and columns the policy names are visible; a per-table row filter bound to the host-asserted project claim isolates tenants at every depth, and a missing claim denies, never widens. Mutations are opt-in and transactional.
row_filter
Multi-tenant SaaS by claim
A row filter can bind a claim from your app's own verified bearer (claims_from_token, with sig / iss / exp / kid checked), so many tenants live as rows in one project, isolated by a claim like tid and never able to override the project.
claims_from_token
Edge query-guard
Parse operations at the edge and reject them before the handler runs when they exceed a depth / complexity limit or (unless allowed) introspect: fragments expanded so nesting can't hide, cyclic ones terminated.
query-guard
Persisted queries + safelist
Clients send a query hash instead of the full query; in safelist mode only pre-registered hashes run and the edge never registers a new one, turning persisted queries into a security allowlist.
persisted
Edge-hidden operations
Mark a subgraph root field internal: callable server-to-server across the supergraph but structurally absent from the anonymous external /graphql edge, failing exactly like an unknown field with no existence oracle.
@edgeHidden
Federation gateway
Register each subgraph's SDL (or let a wasm function self-register on deploy) and boatramp composes + validates a supergraph, then plans and executes a query across subgraphs over the in-process invoke path; the caller's identity is forwarded and re-verified per subgraph.
federated · @key
Subscriptions over SSE
Stream a GraphQL subscription to the browser over graphql-sse, with Last-Event-ID resume, a heartbeat, and the site's stream connection caps.
graphql-sse
GraphiQL & in-process supergraph
A baked GraphiQL IDE (opt-in) for exploring the schema in the browser, and a guest graphql::run capability so a handler runs a safelisted supergraph operation in-process: the same planner, no network hop.
graphiql
03 / MULTI-TENANCY

Many tenants, one hull, isolated by the host.

Host-resolved scoping
Declare tenancy and every SQL, ORM, and GraphQL query is auto-scoped to the caller's tenant, resolved host-side from a verified source (a JWT claim, the routed domain, or a signed context), never supplied or spoofed by guest code.
handlers.tenancy
Per-table scopes
A per-project tenancy schema declares how each table is keyed (tenant-keyed, session-keyed, shared-base, or global reference) and a table you don't declare is refused, deny-by-default, rather than served across tenants.
TableScope
Cross-tenant sharing
One route can serve the caller's own data and another tenant's published subset (storefronts, embeds, share links) host-confined to tenant = B AND <public subset> across ORM, raw SQL, and federated GraphQL, resolved from a routed domain, a signed capability, or a public handle.
@tenant(target)
Anonymous sessions
Host-issued, host-verified signed session cookies give anonymous-first flows (carts, onboarding drafts) a stable identity with no app JWKS or JavaScript, plus a promote verb that claims a session's rows for a tenant at sign-up.
TenantOrSession · promote
RLS backstop
boatramp sets a transaction-local Postgres session variable to the same tenant it injects into every predicate, so your own row-level-security policies enforce the exact same tenancy as a faithful, independent backstop.
session_guc
Per-tenant secrets
A component gets and sets secrets sealed to the caller's own tenant, so each tenant's third-party credentials (a per-firm OAuth secret, per-tenant API or SMTP keys) never live in the app's database.
tenant-secrets
Per-tenant object storage
Every object-store operation is fail-closed to the caller's own containers via a {tenant}-templated allowlist, so one tenant can never read, list, or destroy another's blobs on a shared site.
blobstore_containers
Per-tenant queue fan-in
One consumer with a {tenant} segment in its topic services every per-tenant topic at once (each with its own cursor, dead-letter queue, and lag) and the host dead-letters any message whose sealed tenant doesn't match its topic.
{tenant} topic
04 / CONTAINERS & microVMs

Heavier cargo, still one hull.

Firecracker-class microVMs
Run an OCI image in a hardware-isolated VM with its own kernel, via an embedded rust-vmm VMM.
--isolation untrusted
Native OCI containers
Shared-kernel containers (namespaces, cgroups, seccomp) for code you trust.
--isolation trusted
macOS-native microVMs live seam
On Apple silicon (macOS 15+), each replica runs as a lightweight Linux VM via Apple's Virtualization.framework: strong per-VM isolation, the same compute surface, still one binary.
vmm-vz
Remote Docker
Run workloads against a remote Docker host: the native-container path on Windows and macOS.
remote-docker
Scale-to-zero live seam
Park an idle replica to disk and wake it with its in-RAM state intact: a microVM (Linux KVM or macOS vmm-vz) or a native container (via CRIU). Capability-detected, so a workload only lands on a node that can wake it.
--scale-to-zero
Persistent volumes
Back a container workload with an external volume (a daemon-managed named volume or a host bind-mount) so app state survives restarts and scale-to-zero.
volumes
Managed sql for containers
A docker or native workload can --bind sql and reach the same per-tenant SQL backend a handler gets, over a token-multiplexed shim, so no long-lived database secret ever enters the guest.
--bind sql
Rootless stock images
Run a stock image whose entrypoint chowns its data dir and drops privileges (a database): rootless via --user against a pre-chowned volume, or add just the caps it needs with --cap-add (single-tenant). A managed DB picks the strategy automatically.
--user · --cap-add
Internal service discovery
Co-located workloads, handlers, and functions reach each other (and their managed databases) by name: boatramp runs a per-project DNS responder on the compute bridge, resolving <workload>.<project>.boatramp.internal to a live healthy replica. Source-IP-scoped, so a cross-project lookup is refused.
boatramp.internal
Verified boot + posture
A signed first-party kernel is verified before boot; strict posture forces microVM isolation for untrusted code.
security explain
Cloudflare Containers live seam
The same binary runs on Cloudflare Containers as a single durable instance, with all state in R2 (blobs + a SlateDB KV) so it survives scale-to-zero, fronted by an edge Worker + container Durable Object. Validated end-to-end live.
cloudflare
pre-1.0

Every capability above is implemented and dogfooded; this site runs on it. Interfaces may still shift before 1.0. Start with the quickstart, dig into the docs, or come crew it.