Farther ShoreDocs
Go to Farther Shore
Bring your own backend
Three separate responsibilitiesCreate or bind the originGive the process a runtime tokenWhat the gateway doesNext steps
Scaffold a backend service
Transport modes
Infrastructure with OpenTofu
Deploy on Railway
Deploy on Render
Deploy on AWS
Deploy on Google Cloud
Metering & verification
Runtime tokens
Storing per-user data
@farthershore/backend
Add a backend
Connect a direct backend
Add a webhook consumer
@farthershore/backend exports
@farthershore/backend/express exports
@farthershore/backend/reflect exports
@farthershore/backend/runtime exports
@farthershore/backend/testing exports
@farthershore/backend/webhooks exports
backend-sdk HTTP contracts
Status
Docs/Connect your application/Bring your own backend

Bring your own backend

Decide whether you need a backend, declare its contract, and control inherited or overridden environment origins.

A backend is your always-running HTTP application behind Farther Shore's gateway. You need one when a route must run your code: query your database, call a private provider, process a job, or calculate dynamic usage. You do not need one for platform-owned operations such as subscriptions, API keys, hosted portal data, or request counting at the gateway.

Three separate responsibilities

ResponsibilityOwnerHow it changes
Logical backend and route bindingRepositoryfs.backend() and route refs in business/
Concrete origin for an environmentPlatform operating statefarthershore backend create or backend bind
Application process and databaseYour infrastructureDeploy with your normal host and migration workflow

fs.backend() is a contract declaration. It says which logical backend a route uses, which transport it expects, whether verification is required, and which meters it may report. An origin URL is environment-owned operating state and is intentionally rejected in the Business SDK.

ts
import * as fs from "@farthershore/business";

const requests = fs.requests();

const api = fs.backend("api", {
  name: "Application API",
  transport: { mode: "direct" },
  verification: { required: true },
  default: true,
});

const jobs = fs.route("/v1/jobs", {
  get: { backend: api, requireMember: true },
  post: { backend: api, requireMember: true },
});

fs.plan("starter", {
  kind: fs.plan.kind.free,
  grants: [jobs],
  limits: [requests.perMinute(60)],
});

export default fs.business();

Verification defaults to required, so the explicit line above is useful for readers but not necessary. A single declared backend is the implicit default. With multiple backends, bind every route explicitly or mark exactly one backend as default: true.

Build and push the repository change before binding traffic:

bash
pnpm build
git push
farthershore apply-timeline list my-business

Create or bind the origin

Backends use a stable logical slug across environments. Previews inherit production backends by default; a preview row with a concrete target overrides only that slug in that environment. Concrete overrides and their runtime credentials remain per-environment.

This fallback applies only to the backend's concrete target. The preview's plans, prices, routes, permissions, meters, limits, and policies always come from the Business SDK compiled on its own env/* branch; none of that contract state is inherited from production.

Published routes also address backends by this stable slug, rather than by an environment-specific database ID. The gateway resolves the slug against the effective backend set for the request environment, so binding an override takes effect without changing the Business program or duplicating routes.

Create a direct production backend and bind the origin in one operation:

bash
farthershore backend create my-business \
  --name "Application API" \
  --slug api \
  --transport direct \
  --origin-url https://api.example.com \
  --idempotency-key <persisted-backend-create-attempt-key> \
  --default

Do nothing when the preview should use the production service. To override it, create the corresponding preview row before binding it:

bash
farthershore backend create my-business \
  --name "Application API" \
  --slug api \
  --env staging \
  --idempotency-key <persisted-backend-create-attempt-key> \
  --transport direct

farthershore backend bind my-business api \
  --env staging \
  --origin-url https://api-staging.example.com

backend create is useful when the row does not exist. backend bind updates a direct backend's origin for one environment. A manifest-created preview row with no target remains a placeholder and does not hide the usable production row.

Resolution is preview override, then production, by exact logical slug. It never consults another preview. An environment-only backend with no usable target fails closed with origin_unavailable (HTTP 503).

The same typed 503 origin_unavailable is what callers see whenever the origin cannot be reached — while it is redeploying, stopped, or failing to resolve — and 504 origin_timeout when it accepts the connection but never sends response headers within the route's budget. Your hosting provider's own error page is never relayed, so an outage is never mistaken for one of your application's 404s. Your backend's own JSON responses pass through untouched. See response codes.

For tunnel transport, the platform provisions the origin hostname, so do not pass --origin-url:

bash
farthershore backend create my-business \
  --name "Private API" \
  --slug api \
  --transport tunnel \
  --runner embedded \
  --idempotency-key <persisted-backend-create-attempt-key> \
  --default

See Transport modes before choosing a tunnel.

Give the process a runtime token

The backend SDK bootstraps from FS_RUNTIME_TOKEN. For one deployment serving the business across multiple environments, the simplest default is a business-scoped token: omit both --env and --backend.

bash
farthershore backend tokens create my-business --format json --idempotency-key <persisted-backend-tokens-create-attempt-key>

Store the one-time secret in your host's secret manager, restart or redeploy the service, then verify the binding:

bash
farthershore backend list my-business --format json
farthershore backend tokens list my-business --format json

Use an environment-scoped or backend-scoped token only when the deployment boundary needs that narrower scope. The complete lifecycle is in Runtime tokens.

What the gateway does

For both direct and tunnel transport, the gateway:

  1. resolves the current environment and its compiled route;
  2. selects a concrete environment override or the inherited production backend;
  3. enforces the plan, limits, subject, and route permission;
  4. signs the exact method, path, query, raw body hash, route, backend, and verified principal context;
  5. forwards the request to the resolved origin.

Your process verifies that signature with @farthershore/backend before reading identity or handling the request. Transport changes how packets reach the process; it does not change the trust model.

Next steps

  • Scaffold a backend
  • Verify identity and store user data
  • Report dynamic usage
  • Deploy on Railway or Render
NextScaffold a backend service

On this page

Three separate responsibilitiesCreate or bind the originGive the process a runtime tokenWhat the gateway doesNext steps