Core concepts
This page is the mental model behind everything else in the docs. Read it once and the rest of the reference will make sense. Every noun here — organization, project, deployment, database, function, cronjob, monitor — is a real resource with its own API, lifecycle, and status enum.
Organizations & multi-tenancy
Section titled “Organizations & multi-tenancy”An organization is the tenant that owns everything: projects, databases, functions, cronjobs, monitors, team members, billing, and usage. Every resource is scoped to exactly one organization, and every API call resolves to one organization before it touches data.
psk_API tokens are self-contained — they encode the user, the organization, and the role, so no organization needs to be named on the request.- JWTs (used by the dashboard) carry the user but not the org, so they must pass
?organization_id=or thex-organization-idheader.
Access is role-based (owner, admin, member). Paid features and instance tiers are gated at the organization level: a create call checks whether the org has an active paid plan before it will let you choose a non-free tier or a paid-only feature — a raw API caller cannot sneak a free org onto a paid tier. See Authentication and Organizations & teams.
Card hard-wall. An organization that has never verified a payment card gets 402 on
non-allowlisted routes until a card is verified. This is separate from plan limits.
Projects & deploy types
Section titled “Projects & deploy types”A project is one deployable app. Its deploy type is stored on the slug column and is one of:
| Deploy type | What it is | How it is served |
|---|---|---|
static | A pre-built site or SPA | Published to the global CDN, served with no pod |
container | A long-running server | A Kubernetes pod fronted by a Kong service |
auto | You pick nothing | Classified at create time, then persisted as static or container |
Key facts about projects:
- The name is the address. A project’s
namebecomes its public subdomainhttps://<name>.pandastack.app, so the name is globally unique across all organizations (not just within yours) and must be a valid DNS label: lowercase alphanumerics and hyphens, starting and ending alphanumeric, up to 63 characters. - Static projects build in a microVM (default build command
npm run build) and publish to the CDN origin. An SPA gets anindex.htmlfallback for unmatched routes. A static project connected to Git still runs a server-side build (install + postinstall); only a raw static upload runs no build at all and cannot be redeployed from a repo — you re-upload it. - Container projects run as a pod fronted by a Kong service. On the free tier a container uses scale-to-zero (one replica that sleeps when idle and cold-starts on the next request); paid tiers can enable HPA autoscaling, which is always-warm and mutually exclusive with scale-to-zero.
- Auto-detect builds via the container path with Railpack so the first build always works, while
a classifier decides whether the repo is really a pure static SPA (CDN, no pod) or needs a
container. Classification is asymmetric: it returns
staticonly on positive proof; on any doubt or failure it falls back tocontainer(the safe default). See Auto-detect deploys.
Deployments have their own status enum: queued | running | succeeded | failed.
Deploy backbone
Section titled “Deploy backbone”Creating or deploying a project writes the project/deployment row and a transactional outbox
row (topic deploy.requested) in one database transaction. A relay publishes that message to a
queue; a background worker consumes it and runs the build and rollout. This transactional-outbox
pattern is why write calls return immediately while work continues asynchronously — and it is the
same pattern used by databases (database.provision), cronjobs (cronjob.upsert), and other
resources.
The build pipeline (Railpack buildpacks)
Section titled “The build pipeline (Railpack buildpacks)”For container and auto builds, PandaStack uses Railpack buildpacks, which detect your framework
and language version and build with no build or start command required. The language you pick
on a container project controls how it is built:
language | How it builds |
|---|---|
auto | Railpack buildpacks — zero-config framework + runtime detection |
nodejs | Platform-generated Dockerfile (requires a start command) |
python | Platform-generated Dockerfile (requires build and start commands) |
go | Platform-generated Dockerfile (requires build and start commands) |
docker | Your repository’s own Dockerfile |
auto and static are exempt from build/start commands — Railpack and defaults figure them out.
Before any build runs (for container, auto, and Git-based static), a source scan rejects malware
and abuse kits. Full detail lives in Build & buildpacks.
The gateway
Section titled “The gateway”All project traffic — static and container — is fronted by the PandaStack gateway. Every project carries a routing manifest that the gateway walks in order for each request:
- Redirects / rewrites (matched by rule type)
- Headers (applied as one global set-and-continue rule to all paths)
- Function dispatch (container manifests have a single catch-all route to the pod; static manifests have none)
- SPA fallback (for static SPAs)
- Implicit 404
The static filesystem step (the manifest’s static.target, pointing at the CDN origin) is tried
before rewrites and before the SPA fallback. Redirect status codes mirror the serving plane:
static redirects are 302, container redirects are 301. Because everything flows through
the gateway, it is also where bandwidth accounting, analytics/metrics capture, and per-project rules
are enforced. See Redirects, rewrites & headers and
Custom domains.
Environments: build-time vs. runtime
Section titled “Environments: build-time vs. runtime”Configuration reaches your app as two separate lists:
| List | Stored as | Returned in responses? | On the wire |
|---|---|---|---|
env | [{ name, value }] | Yes | Plaintext |
secrets | Base64 of JSON([{ name, value }]) | Never | Encrypted (iv:cipher) |
There is no separate build-time vs. runtime field in the schema — env flows to the build image and
the running app the same way for every deploy type. The practical split is framework-driven: for a
static / SPA build, only variables the framework exposes at build time reach the client bundle —
for example NEXT_PUBLIC_* for Next.js. Runtime-only secrets are not baked into a static build.
Reserved/system variables are guarded against override. See
Environment variables & secrets.
First-class resources
Section titled “First-class resources”Beyond projects, PandaStack exposes several resources, each with its own create/lifecycle API and
status enum. Most are paid features (a free organization receives a 402 upgrade prompt).
| Resource | What it is | Engine / runtime | Paid-only? | Status enum |
|---|---|---|---|---|
| Database | Managed PostgreSQL / MySQL | KubeBlocks (Cluster CR) | Free tier: 1 per org; paid for tiers/HA | pending, running, failed, deploying, updating, deleting, queued, stopped |
| Function | Edge function (code + zip) | nodejs (index.js) / python (main.py) | Yes | version-tracked; invocations logged |
| Scheduled function | An existing function on a cron | fn-invoker microVM | Requires functions (paid) | tracks lastRunAt / nextRunAt / lastStatus |
| Cronjob | Scheduled container build+run | Container CronJob | Yes | pending, deploying, running, failed, deleting, deleted, updating, paused |
| Monitor | URL uptime/health check | pg-boss scheduler | Yes | running or pause (live UP/DOWN derived from last heartbeat) |
A few load-bearing details:
- Databases are reached through the
*.db.pandastack.appproxy. Postgres clients route by SNI; MySQL clients send no SNI, so a public MySQL connection routes by a key encoded in the username (root.<dbname>). Connection URLs are returned masked (********) until a role-gated reveal. A free database is single-zone and auto-expires 30 days after creation (suspend at 30 days, purge 14 days later); paid databases never expire. See Databases. - Functions are name-based: the public invoke endpoint is
POST /v1/functions/{name}/invoke, where{name}includes a random 6-character suffix minted at create time. Uploading new code increments a version; metadata-only edits do not. See Functions. - Cronjobs run either a build from a repo (
github) or a public image directly (public_image, e.g.nginx:latest), on a 5-field cron schedule, with a full lifecycle (create, update, delete, pause, resume, run-now). See Cronjobs. - Monitors ping a URL on an interval and store heartbeats; the persisted row is only
runningorpause, while live health is derived from the latest heartbeat. See Uptime monitors.
Metrics vs. analytics
Section titled “Metrics vs. analytics”PandaStack captures request data server-side at the gateway — there is no client SDK. Both metrics and analytics read from a ClickHouse event log, are tenant-safe (the project is ownership-checked in Postgres before any query), and fail open (if ClickHouse is unavailable the endpoints return an empty, disabled shape rather than an error).
| Metrics | Analytics | |
|---|---|---|
| Answers | Performance & health | Audience |
| Fields | requests, errors, error rate, p50/p95/p99 latency, bandwidth, unique visitors, RPS | unique visitors, views, returning visitors, top countries/referrers/pages, browsers, devices |
| Gating | Available | Paid feature and the project’s enable_analytics toggle |
| Bots | Counted | Excluded from audience counts |
Both share the same time ranges — 1h, 24h, 7d, 30d — each with its own bucket width. See
Metrics and Analytics.
Plans, tiers & usage
Section titled “Plans, tiers & usage”Instance tiers (from free-tier up to m2-2xmemory-tier) set the CPU/RAM (and, for databases,
disk) a workload gets; the same tier list and pricing applies to both container apps and databases.
Plan limits (free / pro / premium / enterprise) set counts and monthly allowances and unlock
paid-only features. Usage is metered on billable dimensions and billed for paid plans only; free
plans never pay usage. See Plans & limits, Instance tiers, and
Usage & metering.
Related pages
Section titled “Related pages”- Quickstart — deploy your first project
- Regions — where things run
- Projects overview — the full project surface
- API reference — every endpoint