MainSDK
Search⌘K
Architecture

Cloud and regions

What MainSDK Cloud stores, in which of three regions, how a project joins it, and why a Cloud limit never breaks your app.

Planned for 0.6

Status Status is where the work is: Planned (in a milestone, not started), Building (tickets in progress), Preview (usable, may change), then the stability it ships at.

Stability The promise an interface ships with.

  • Stable Follows semantic versioning; breaking changes need a new major, 12 months of overlap and a codemod.
  • Beta Usable in production; may change before it becomes stable.
  • Experimental May change or go away; needs an explicit opt-in in main.yaml.
Stability levels
Updated 2026-10-28

MainSDK Cloud is optional. Your app and every check work without it. When you do log in, your project's data stays in the region you chose: US, EU or India. Cloud arrives in phase 2 (milestone 0.6).

Three regions

flowchart TB
  app["Your app<br/>project: { id, region: eu }"] -- "events, traces, decisions" --> eui
  subgraph usr["US region"]
    usi["Ingest"] --> uss[("Store")]
  end
  subgraph eur["EU region"]
    eui["Ingest"] --> eus[("Store")]
  end
  subgraph india["India region"]
    ini["Ingest"] --> ins[("Store")]
  end
  wrong["Call reaches the wrong region"] --> usi
  usi -. "forward or refuse with RFC 9457,<br/>store nothing" .-> eui
Diagram
  • Each project's events, traces and decisions are kept in its chosen region. A call that reaches another region's endpoint is forwarded or refused, and nothing is stored there.
  • Every region is included on every plan at no extra cost. There is no data region add-on.
  • Still open: the default region when you don't choose one (taken from main.yaml or asked at login).

Your app's own data follows the same three regions (ADR-0006): db keeps one store per region and writes each record to its owner's region, check refuses queries that join across regions, analytics combine regions only as totals, and moving a user between regions is an audited job.

What Cloud stores

StoredNotes
Projects, environments and keysKeys shown masked in the console
Events: trace spans, log lines, errors, policy decisions, gate runs, action callsRedacted in your app before they are sent
History7 days on Free, 30 days on Teams

What Cloud never needs: your request path. See request lifecycle.

Joining Cloud

sequenceDiagram
  participant D as You
  participant C as mainsdk CLI
  participant B as Browser
  participant M as MainSDK Cloud
  D->>C: mainsdk init (no account, no network)
  C->>C: write project id (UUIDv7) to main.yaml
  D->>C: mainsdk login --region eu
  C->>M: device authorization (RFC 8628)
  M-->>C: short code
  D->>B: approve the code
  M-->>C: project claimed, same prj_ id
  C->>M: optional: upload the last 7 days of local events
Diagram
  • The project id is not a credential. It is a UUIDv7 in main.yaml, shown as prj_01JC8Q…. A public repo shows it, so only an ingest key or a platform OIDC token can send data.
  • No copying keys. Login uses the device flow; you approve a code in the browser.
  • Ingest keys: one per environment. msk_live_… for prod, msk_test_… for dev and stage, so secret scanners catch leaks. In CI and on Vercel, the platform's OIDC token replaces the key.
  • Forks get a new id. If an id is already claimed under a different git remote, login offers a new one; mainsdk init --new-id does it by hand.
  • Logout stops sending at once. The app and every check keep working locally.

Every call carries the wire contract version in a mainsdk-protocol header. The Cloud supports the current and two previous SDK majors.

The 402 rule

Only what reaches our Cloud is metered. Your machine is never metered, and security is never metered.

flowchart LR
  a["0–80%<br/>free allowance"] --> w["80%<br/>warning in CLI and email"]
  w --> g["100% to 120%, or 7 days<br/>grace"]
  g --> c{"Card on file?"}
  c -- yes --> p["Pay per 100,000 events<br/>up to your monthly cap"]
  c -- no --> e["HTTP 402 from Cloud only"]
  p -- cap reached --> e
Diagram
json
{ "type": "https://mainsdk.dev/errors/MAIN-CLOUD-0402", "title": "Free allowance used",
  "status": 402, "detail": "50,000 events used this month. Add a card or move to Teams." }

After a 402, events stop going online and hosted reviewers stop. Your app keeps running, every check, gate, guarantee and runtime enforcement keeps working, and logs stay in your terminal (ADR-0003, ADR-0007).

The allowance of 50,000 events a month is a proposal. The price per 100,000 events and per hosted reviewer run is not set yet.

Production access

Any access to production data in Cloud needs SSO or a passkey with phishing-resistant MFA (ADR-0008). Production live tail and debug sessions ask for a fresh passkey no older than 5 minutes. MainSDK staff follow the same rules and appear in the same project audit view. There is no remote shell into production.

Later

WhatPhase
Organisations, project transfer, SSO and SCIM for the console (Teams)2
Self-hosted and air-gapped control planes with PKI-signed licences4 (Fleet)

Next

Was this page helpful?

↑↓ moveEnter openEsc close

Not decided yet