Docs/Services/Standard backend (OpenKBS Cloud)

Standard backend (OpenKBS Cloud)

Run your functions and Postgres on OpenKBS Cloud instead of AWS Lambda and Neon: same CLI and handler contract, with only the real differences documented here.

2 min readUpdated

With "backend": "standard" in openkbs.json, a project's functions and Postgres run on OpenKBS Cloud instead of AWS Lambda/Neon. Everything else — sites, storage, CloudFront, mail, domains, MQTT, AI proxy — is identical to Elastic projects, and all CLI commands and the function handler contract work exactly the same. This page covers only the real differences.

No implicit AWS credentials

Code using the AWS SDK without explicit keys (e.g. new S3Client() relying on a Lambda execution role) fails — there is no IAM role on the Standard backend. For file storage, use the platform API instead:

javascript
const res = await fetch(`https://project.openkbs.com/projects/${process.env.OPENKBS_PROJECT_ID}/storage/upload-url`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.OPENKBS_API_KEY}` },
  body: JSON.stringify({ key: 'media/uploads/photo.jpg', contentType: 'image/jpeg' }),
});
const { uploadUrl, publicUrl } = await res.json();

Files still land on S3 and are served through CloudFront exactly as on Elastic.

Function URLs

openkbs fn deploy prints URLs like https://api--ab12cd34.node1.openkbs.com (instead of *.lambda-url.*.on.aws). Use them the same way — including as the frontend API_BASE. CloudFront /fn/* routing works identically.

Schedules

Full cron support — both AWS forms work:

  • rate(N minutes|hours|days)
  • cron(M H DOM MON DOW *) — standard cron semantics, ? treated as *. The trailing year field must be *.

Postgres

  • DATABASE_URL is injected as usual; the host is a db.<node> hostname with a valid TLS certificate — ssl: { rejectUnauthorized: true } works.
  • openkbs postgres migrate is not applicable on Standard.

Point-in-time restore (self-service, 7-day window)

The database is continuously backed up (every transaction). To recover data — for example after rows were accidentally deleted:

bash
openkbs postgres restore --point-in-time "2026-07-05T17:03:55Z"   # moment BEFORE the accident (UTC)
openkbs postgres restore-status    # poll until "available" (typically 1-5 min)

restore-status returns a connection string to a restored copy (db_<id>_restore) — the live database is never touched. Connect to both and copy back exactly what's needed (same role/password, so one client, two connections):

javascript
import pg from 'pg';
const live = new pg.Client({ connectionString: process.env.DATABASE_URL, ssl: { rejectUnauthorized: true } });
const snap = new pg.Client({ connectionString: RESTORED_CONNECTION_STRING, ssl: { rejectUnauthorized: true } });
// e.g. re-insert rows that exist in the snapshot but not live:
// SELECT from snap → INSERT INTO live (preserve ids with OVERRIDING SYSTEM VALUE if needed)

When done, release the copy:

bash
openkbs postgres restore-cleanup

One restore runs at a time per node; a second request while one is in progress returns an error — retry after a few minutes.

Runtime behavior

Functions are long-running processes handling requests concurrently (no cold starts, wake from idle in under a second). Avoid mutable global state that assumes one-request-at-a-time; per-request state belongs inside the handler. Connection pools and caches in module scope are fine and encouraged.

Building something for your company?
We co-build production systems with enterprise teams on this platform.