# jaydb > Ship apps with no backend at all. An app is a folder of static files; jaydb is > both the login and the database, reached straight from the browser. There is no > server of your own to run — not a serverless function, not a BaaS SDK, no API > tier, no auth service, no session store. > Each end user signs in with their own identity through a per-tenant OIDC issuer, > so the browser talks to the data plane directly with a token scoped to that user > and nothing confidential ships to the front end. > Billing is per document operation with no monthly floor. Free every month: > 1 GB stored, 100,000 reads, 10,000 writes. ## What jaydb replaces The competitor is not "a faster database" — it is the entire backend layer you used to stand up before your first user showed up: auth service, API tier, session store, ORM, connection pool, deploy pipeline, and an always-on bill. This is not "serverless" in the functions sense. Serverless functions still boot a server per request that you write, deploy, and version. jaydb removes the layer entirely; the only always-on system is jaydb, which you do not operate. ## Two ways to build 1. **Frontend-only app (the default).** Static files on any CDN or static host. Users sign in through your org's OIDC issuer with PKCE; the browser receives its own bearer token and calls the data plane directly. No server of yours is involved at any point. Use the official `@jaydb/cloud` zero-dependency SDK for turnkey PKCE authentication, automatic token refresh, and typed CAS operations. 2. **Server-side integration.** A backend or script holds an `X-JayDB-API-Key` and calls the same data plane. A backend is optional, never required to start. ## What it is good for - Frontend-only apps that need real per-user login and shared state. - Read-heavy access by key or by key prefix. - State scoped to a user, a tenant, a document, or a session. - Collaborative state where two writers rarely touch the same document at once. - Projects that must cost nothing while idle. - Cases where the option to self-host the same engine later matters. ## What it is NOT good for Do not choose jaydb for these; pick a relational or search database instead. - Joins across entities, or enforced foreign keys. - Atomic writes spanning several documents. - Querying by field value. There are no secondary indexes and no ad-hoc queries; access is by key or key prefix only. - Full-text search or aggregation. - Sustained concurrent writes to a single hot key. Optimistic concurrency degrades into retries under real contention. ## Identity, without an identity server Every organization gets its own OIDC issuer: https://{tenant}.jaydb.com It publishes standard OIDC discovery metadata and a JWKS under that issuer, so tokens are verifiable with any standard OIDC library. - **Authorization Code + PKCE** for public browser clients. No client secret ships to the browser — the PKCE proof key replaces it. - **Bring your own identity providers.** Org admins connect Google, GitHub, Microsoft, any generic OIDC provider, or a custom OAuth2 provider from the console. - **Register the app** (client ID, redirect URIs, allowed origins) as a public PKCE client in the console. Registering the app is what grants its origin cross-origin access — there is no operator-managed allowlist to edit. ### Browser sign-in flow 1. Redirect the user to the org's authorize endpoint: https://{tenant}.jaydb.com/oauth/v2/authorize ?response_type=code &client_id={public_client_id} &redirect_uri={your_redirect_uri} &scope=openid profile email &code_challenge={s256_challenge} &code_challenge_method=S256 2. Exchange the returned code at the token endpoint, form-encoded, with the original `code_verifier`: POST https://{tenant}.jaydb.com/oauth/v2/token 3. Call the data plane with the resulting bearer token. ## API Base URL is a tenant subdomain. Requests to a non-tenant host are rejected 403. https://{tenant}.jaydb.com/v1/n/{namespace}/docs/{key} Authentication — one of these two headers on every request: - `Authorization: Bearer ` — an OIDC token minted by the tenant's issuer, used by frontend-only browser apps. Scoped to the signed-in user. - `X-JayDB-API-Key: ` — a long-lived secret for server-side and REST integrations, where the secret stays server-side. A namespace is created implicitly by the first write to it. ### Read a document GET /v1/n/{namespace}/docs/{key} 200 with the JSON document as the body. The `ETag` response header carries the current version. 404 if the key does not exist. ### Write a document PUT /v1/n/{namespace}/docs/{key} Body is the JSON document. Response: { "status": "ok", "key": "...", "etag": "...", "mod_time": "..." } Conditional headers, both optional: - `If-Match: ` — write only if the document is still at that version. Returns 412 if it moved. This is compare-and-swap. - `If-None-Match: *` — create only. Returns 412 if the key already exists. Quotes around the etag are accepted and ignored, so echoing the `ETag` response header back verbatim works. ### Delete a document DELETE /v1/n/{namespace}/docs/{key} Accepts `If-Match: ` for a conditional delete. Deletes are never billed. ### List keys GET /v1/n/{namespace}/docs?list&prefix={prefix}&limit={n} `limit` defaults to 100, maximum 1000. Returns items carrying `key`, `etag`, `mod_time` and `size`, plus `next_cursor` when more remain. Pass the cursor back as `&cursor=` to continue. ### Browser notes - The `ETag` response header is exposed cross-origin, so browser clients can read it and use it for compare-and-swap. - There is no subscription, SSE, or websocket. Clients poll; list returns a per-key `etag`, so a poll loop can diff and re-read only what changed. ## Status codes - 200 — success - 400 — malformed path or invalid JSON body - 401 / 403 — missing or invalid credential, or a non-tenant host - 404 — no such document - 412 — a conditional header did not match; re-read and retry - 413 — request body over the size limit ## Pricing - Storage: $0.05 per GB-month, metered per megabyte-hour - Reads: $0.20 per million, metered per single read - Writes: $0.50 per million, metered per single write - Deletes: free - Egress: included, fair use - Free every month, on every account: 1 GB, 100,000 reads, 10,000 writes - Optional prepaid packs: $5 buys $6.50 of usage, $10 buys $15 There is no monthly floor and no per-seat charge. Usage above the free allowance is billed at the rates above with no step changes. Sign-in and identity are part of the platform, not a separately priced add-on, and are not billed per active user. ## Worked cost example 20 GB stored, 5,000,000 reads, 1,000,000 writes in a month: storage (20 - 1) GB x $0.05 = $0.95 reads (5M - 100k) x $0.20/M = $0.98 writes (1M - 10k) x $0.50/M = $0.495 total = $2.43 ## Concurrency pattern Read the document, keep its `ETag`, send the change back with `If-Match`, and retry on 412. That is the entire synchronisation primitive — there is no subscription to manage and no transaction to open. ## Usage example: Kanban demo app For a complete, working reference app built with zero backend servers and the official `@jaydb/cloud` Frontend SDK, see the **JayDB Kanban Demo**: - Live Demo: https://jaydb-cloud.github.io/jaydb-kanban-demo/ - Source Code: https://github.com/jaydb-cloud/jaydb-kanban-demo This demonstrates: - **Pure static frontend**: Static HTML and JavaScript hosted on GitHub Pages with no backend servers, lambdas, or API proxies. - **Browser sign-in (OIDC + PKCE)**: End-user login via Google or GitHub against the tenant's OIDC issuer (`/oauth/v2/authorize` and `/oauth/v2/token`), powered by `@jaydb/cloud`'s `Auth` module with silent token refresh. - **Direct database access**: Reading, creating, and deleting cards directly from the browser using `@jaydb/cloud`'s `JayDB` client with Bearer tokens. - **Conflict-free collaboration (CAS)**: Card movement and editing guarded with `ifMatch: `. When two users move a card concurrently, `ConflictError` (HTTP 412) triggers an automatic re-fetch and retry. - **Multi-user sync and presence**: Document prefix listing (`db.list({ prefix: 'cards/' })`) polled periodically to diff ETags and synchronize state across browsers without WebSockets. ## Engine & SDK - Engine: Open-source jaydb engine, MIT licensed: https://github.com/jaydb-cloud/jaydb - Frontend SDK: Official zero-dependency browser SDK (`@jaydb/cloud`): - Documentation: https://jaydb-cloud.github.io/jaydb-cloud-sdk/ - Repository: https://github.com/jaydb-cloud/jaydb-cloud-sdk - ESM CDN: `https://jaydb-cloud.github.io/jaydb-cloud-sdk/jaydb-cloud.esm.min.js` ## Links - Full API spec, single file: https://jaydb.com/api.md - Documentation: https://jaydb.com/docs/ - Frontend SDK Docs: https://jaydb-cloud.github.io/jaydb-cloud-sdk/ - Frontend SDK Repo: https://github.com/jaydb-cloud/jaydb-cloud-sdk - Source: https://github.com/jaydb-cloud/jaydb - Kanban Demo App (Live): https://jaydb-cloud.github.io/jaydb-kanban-demo/ - Kanban Demo App (Source): https://github.com/jaydb-cloud/jaydb-kanban-demo