Rindle Cloud

Connect your app to Rindle Cloud

Connect SQL services and synced apps to Rindle Cloud with one ingress URL and one server-only database token.

View as Markdown

You provisioned an app on Rindle Cloud (if not, start with the Cloud quickstart). The managed connection is the same shape that rindle dev injects locally: one application ingress and one trusted credential.

The two values on your dashboard

Open the app’s Connect panel:

Value Purpose
RINDLE_URL Unified HTTPS ingress for SQL, migrations, reads, leases, and subscriptions
RINDLE_DATABASE_TOKEN Database-wide bearer for trusted server code

An app URL looks like https://app-<id>.rindle.cloud. The edge routes each protocol to the right process: writes reach the HCTree master. Sync reads and live-query traffic reach its follower. You do not configure master, follower, control-plane, or WebSocket addresses separately.

The token is a per-app secret. Put it in the API server’s secret store, never source control or browser-visible environment variables.

SQL services and scripts

Use @rindle/sql-client for a SQL-plan app or ordinary server-side SQL against either plan:

import { createSqlClient } from "@rindle/sql-client";

export const db = createSqlClient({
  url: process.env.RINDLE_URL!,
  authToken: process.env.RINDLE_DATABASE_TOKEN!,
});

const rows = await db.execute({
  sql: "select id, title from issue where status = ?",
  args: ["open"],
});

The CLI uses the same values:

rindle sql "select count(*) from issue"
rindle sql --file scripts/backfill.sql

Several statements passed to rindle sql are applied as one atomic batch. For versioned schema or data changes, use rindle migrate apply instead.

Synced app API server

On the Sync plan, give createRindleApiServer the unified connection. It derives its read/control and SQL transports internally:

import { createRindleApiServer } from "@rindle/api-server";
import { schema, queries, mutators } from "./shared/rindle";

export const api = createRindleApiServer({
  rindle: {
    url: process.env.RINDLE_URL!,
    token: process.env.RINDLE_DATABASE_TOKEN!,
  },
  schema,
  queries,
  mutators,
});

The API server can run anywhere with fetch: a Node process, Worker, Lambda, or another server runtime. All trusted calls use the one bearer. It never reaches the browser.

Browser client

The browser points only at your API server:

import { createRindleClient } from "@rindle/optimistic";
import { schema, mutators } from "./shared/rindle";

const app = await createRindleClient({
  schema,
  mutators,
  user: () => currentUser(),
  api: { url: "" }, // same-origin /api/rindle/* routes
});

There is no browser topology configuration. Its first authorized query lease returns the public WebSocket endpoint and a signed follower-affinity ticket. The ticket keeps lease and subscription traffic on the same follower, but it is placement metadata, not authorization. Your API server still authorizes every named query.

Local and Cloud use the same contract

Local development Rindle Cloud
RINDLE_URL injected by rindle dev copied from Connect
RINDLE_DATABASE_TOKEN injected by rindle dev copied from Connect
Data tier local master, follower, and rindle-dev-edge packed OVH processes behind Cloudflare Tunnel
Browser setup API URL only API URL only

Your schema, queries, mutators, SQL calls, and browser setup do not change between the two environments.

Migrations

After rindle deploy or rindle link has written .rindle/cloud.json, apply the same ordered migration files remotely:

rindle migrate status --cloud
rindle migrate apply --cloud

The binding is safe to commit. It identifies the app but contains no database token. The CLI authenticates the Cloud proxy with your rindle login session.

Next steps