Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions apps/docs/content/guides/choose-cache.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ description: "**Use Valkey.** KeyDB development has stalled and is effectively d
## Valkey (Default Choice)

- Redis-compatible drop-in replacement
- Type: `valkey:single@7.2` (single) or `valkey:ha@7.2` (HA) — only v7.2 is supported (the platform rejects `valkey@8` at import, `serviceStackTypeNotFound`)
- Profile (scaling tier): `hobby` for dev, `staging` for production; escalate to `production` only on a clear load signal
- Connection: `redis://${hostname}:6379` — Valkey runs **unauthenticated** on Zerops; there are NO `user`/`password` env vars. Do **not** template `${cache_user}`/`${cache_password}` — they don't exist and produce a broken DSN
- **HA vs single → the `type` variant:** `valkey:single@7.2` (default) / `valkey:ha@7.2`. Only `7.2` exists — the platform rejects `valkey@8` (`serviceStackTypeNotFound`).
- **Scaling tier → the `profile` field:** `hobby` / `staging` *(default)* / `production`. Recommend `hobby` for dev (cheapest), `staging` for production; escalate to `production` only on a clear load signal. Omitting `profile` applies `staging`.
- **Legacy form** (older YAML / existing services): `type: valkey@7.2` + `mode:` — `mode: NON_HA` ≡ `:single`, `mode: HA` ≡ `:ha`. Still accepted (remaps to the variant) but `mode` is deprecated; author new YAML as the variant + profile.
- Connection: Valkey **requires auth** on Zerops — use `${cache_connectionString}` (full auth'd URL) or supply `${cache_password}` (e.g. `REDIS_PASSWORD: ${cache_password}`). There is no separate `${cache_user}` (default user + password); an unauthenticated `redis://${hostname}:6379` fails with `NOAUTH Authentication required`.
48 changes: 41 additions & 7 deletions apps/docs/content/guides/choose-database.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,59 @@ title: "Choosing a Database on Zerops"
description: "**Use PostgreSQL** for everything unless you have a specific reason not to. It's the best-supported database on Zerops with full HA, read replicas, and pgBouncer."
---

**Use PostgreSQL** for everything unless you have a specific reason not to — the best-supported database on Zerops, with optional HA, read replicas, and pgBouncer. HA vs single node is set in the type (`postgresql:single@<ver>` / `postgresql:ha@<ver>`) and is immutable; legacy `mode: NON_HA`/`HA` is deprecated (`NON_HA` ≡ `:single`, `HA` ≡ `:ha`).
**Use PostgreSQL** for everything unless you have a specific reason not to — the best-supported database on Zerops, with optional HA, read replicas, and pgBouncer.

## Decision Matrix

| Need | Choice | Why |
|------|--------|-----|
| **General-purpose** | **PostgreSQL** (default) | Optional HA, read replicas, pgBouncer, best Zerops support |
| MySQL compatibility | MariaDB | MaxScale routing, async replication |
| Analytics / OLAP | ClickHouse | Columnar storage, ReplicatedMergeTree, 4 protocol ports |
| Analytics / OLAP | ClickHouse | Columnar storage, ReplicatedMergeTree |

## PostgreSQL (Default Choice)
## PostgreSQL — two import-YAML choices, both fixed for the service's life

- Type + scaling: `postgresql:single@<ver>` (single node, dev) or `postgresql:ha@<ver>` (HA cluster). Add a `profile` (scaling tier) — set it explicitly and escalate only on a clear signal: `oltp-hobby` for dev, `oltp-staging` for production, moving up to `oltp-production` / `oltp-enterprise` only when load clearly needs it. Omitting it applies the default (single → `oltp-staging`, HA → `oltp-production` = dedicated CPU). See [PostgreSQL scaling](/postgresql/how-to/scale)
- Connection: the generated `${connectionString}` is `postgresql://${user}:${password}@${hostname}:5432` (no database path). Append `/${dbName}` yourself if your driver needs one — the db-name var is `dbName` (default `db`)
**1. HA vs single node → the `type` variant** (NOT a `mode:` field):

- `postgresql:single@<ver>` — one node. Default for dev and most apps.
- `postgresql:ha@<ver>` — 3-node cluster + proxies. Production-grade; resources start at the production tier.

**2. Scaling tier → the `profile` field** (autoscaling envelope + PostgreSQL tuning preset):

| Workload | `:single` profile | `:ha` profile |
|---|---|---|
| dev / prototype / learning — cheapest | **`oltp-hobby`** | — (HA has no hobby) |
| staging / early-stage app | `oltp-staging` *(single default)* | `oltp-staging` |
| business-critical transactional | `oltp-production` | `oltp-production` *(HA default)* |
| high-throughput OLTP at scale | — | `oltp-enterprise` |
| analytics / warehouse | `olap-production` | `olap-production` |
| ingestion / write-heavy | `writeheavy-production` | `writeheavy-production` |

**Recommended defaults — set `profile` explicitly; escalate only on a clear signal:** dev → `postgresql:single@<ver>` + `profile: oltp-hobby` (lowest cost); production → `profile: oltp-staging` (move to `oltp-production` / `oltp-enterprise` only when load clearly warrants it). Omitting `profile` applies the default — single → `oltp-staging`, **HA → `oltp-production` (dedicated CPU + high minima)** — which over-provisions HA.

```yaml
services:
- hostname: db # dev — cheapest
type: postgresql:single@18
profile: oltp-hobby
- hostname: db # production HA — default tier (profile optional)
type: postgresql:ha@18
profile: oltp-production
```

- `profileOverrides` (individual params: `work_mem`, `max_wal_size`, `autovacuum_*`, …) is valid **only** with `profile: custom`.
- `verticalAutoscaling` (CPU mode, min/max CPU/RAM/disk) tightens the envelope on top of any profile — no need for `custom` just to resize.

**Legacy form — you may still meet it** in older YAML, recipes, or existing services: `type: postgresql@<ver>` + a separate `mode:` field. The mapping is `mode: NON_HA` ≡ `:single`, `mode: HA` ≡ `:ha`. The platform still accepts the legacy form (it remaps to the variant) but `mode` is **deprecated and ignored by validation**. Author new YAML as `:single`/`:ha` + `profile`; treat a discovered `mode:` as its equivalent variant.

- Connection: the generated `${connectionString}` is `postgresql://${user}:${password}@${hostname}:5432` (no database path). Append `/${dbName}` yourself if your driver needs one — the db-name var is `dbName` (default `db`).

## MariaDB

- Connection: the generated `${connectionString}` is `mysql://${user}:${password}@${hostname}:3306` (no database path); append `/${dbName}` if your driver needs one
- Type variant: `mariadb:single@<ver>` / `mariadb:ha@<ver>`. No `profile` — scale with `verticalAutoscaling`.
- Connection: the generated `${connectionString}` is `mysql://${user}:${password}@${hostname}:3306` (no database path); append `/${dbName}` if your driver needs one.

## ClickHouse

- HA: replicated databases use a `Replicated(...)` engine `ON CLUSTER`; tables use a `Replicated*MergeTree` engine (without `ON CLUSTER`)
- Type variant: `clickhouse:single@<ver>` / `clickhouse:ha@<ver>`. No `profile` — scale with `verticalAutoscaling`.
- HA: replicated databases use a `Replicated(...)` engine `ON CLUSTER`; tables use a `Replicated*MergeTree` engine (without `ON CLUSTER`).
13 changes: 8 additions & 5 deletions apps/docs/content/guides/production-checklist.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ title: "Production Checklist for Zerops"
description: "Before going to production: (1) databases to HA mode, (2) minContainers: 2 on app services, (3) replace Mailpit with real SMTP, (4) remove Adminer, (5) use Object Storage for uploads, (6) use Redis/Valkey for sessions."
---

Before going to production: (1) databases to HA mode, (2) minContainers: 2 on app services, (3) replace Mailpit with real SMTP, (4) remove Adminer, (5) use Object Storage for uploads, (6) use Valkey for sessions.
Before going to production: (1) databases to HA (the `:ha` type variant), (2) minContainers: 2 on app services, (3) replace Mailpit with real SMTP, (4) remove Adminer, (5) use Object Storage for uploads, (6) use Valkey for sessions.

## Database

| Item | Dev | Production |
|------|-----|------------|
| Deployment variant | `:single` | `:ha` (must recreate) |
| Deployment variant | `:single` (e.g. `postgresql:single@18`) | `:ha` (e.g. `postgresql:ha@18`) — must recreate |
| Scaling profile | `oltp-hobby` | `oltp-staging` (escalate to `oltp-production` only on clear load) |
| Backups | Optional | Enabled |
| Connection | Single primary | Primary + read replicas |

**The deployment variant is immutable** — cannot switch after creation. Delete and recreate with the `:ha` type variant (e.g. `postgresql:ha@16`).
**HA is immutable** — cannot switch after creation. Delete and recreate with the `:ha` variant.

**Legacy form** you may still see in older YAML or existing services: `type: postgresql@18` + a separate `mode:` field — `mode: NON_HA` ≡ `:single`, `mode: HA` ≡ `:ha`. Still accepted (remapped to the variant) but `mode` is deprecated and ignored by validation; author new YAML in the variant form.

## Application Services

Expand Down Expand Up @@ -90,7 +93,7 @@ Remove entirely or disable `enableSubdomainAccess`. Use VPN + pgAdmin/DBeaver lo

```yaml
- hostname: cache
type: valkey:single@7.2 # use valkey:ha@7.2 for production
type: valkey:single@7.2 # valkey:ha@7.2 for production
```

## Framework-Specific Production Settings
Expand Down Expand Up @@ -135,7 +138,7 @@ Remove entirely or disable `enableSubdomainAccess`. Use VPN + pgAdmin/DBeaver lo
| CPU mode | `cpuMode: DEDICATED` for consistent performance under load |
| Environment separation | Separate projects for dev/staging/prod |
| Stateless design | Sessions in Valkey, uploads in Object Storage — no local state |
| Database variant | `<svc>:ha@<ver>` for all managed services (immutable — plan before creation) |
| Database HA | the `:ha` type variant for all HA-capable managed services (immutable — plan before creation) |
| Min containers | `minContainers: 2+` on app services for throughput + crash-tolerance (rolling deploys are already zero-downtime at any count via the default `temporaryShutdown: false` — don't conflate the two) |

## Health Check Pattern
Expand Down
11 changes: 6 additions & 5 deletions apps/docs/content/guides/scaling.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "Scaling and Autoscaling"
description: "Zerops autoscales vertically (CPU/RAM/disk) and horizontally (container count). Runtimes support both. Managed services (DB, cache, shared-storage) support vertical only with fixed container count (`:single`=1, `:ha`=3). Object-storage and Docker have no autoscaling. Extends grammar.md section 9 with mechanics, thresholds, YAML syntax, and common mistakes."
---

Zerops autoscales vertically (CPU/RAM/disk) and horizontally (container count). Runtimes support both. Managed services (DB, cache, shared-storage) support vertical only with fixed container count (`:single`=1, `:ha`=3). Object-storage and Docker have no autoscaling. Extends grammar.md section 9 with mechanics, thresholds, YAML syntax, and common mistakes.
Zerops autoscales vertically (CPU/RAM/disk) and horizontally (container count). Runtimes support both. Managed services (DB, cache, shared-storage) support vertical only with fixed container count (the `:single` type variant = 1 node, `:ha` = 3). Object-storage and Docker have no autoscaling. Extends grammar.md section 9 with mechanics, thresholds, YAML syntax, and common mistakes.

## When to Scale Which Way

Expand Down Expand Up @@ -111,12 +111,14 @@ Applies to **runtimes and Linux containers only**. New containers are added when

### Managed Services (DB, Cache, Shared Storage)

Container count is **fixed by the deployment variant** (`:single` / `:ha` in the type), set at creation, **immutable**:
Container count is **fixed by the deployment variant in the type** (`postgresql:single@18` / `postgresql:ha@18`), set at creation, **immutable**:

| Variant | Containers | Use case |
|---|---|---|
| `<svc>:single` | 1 | Development, non-critical |
| `<svc>:ha` | 3 (on separate physical machines) | Production, automatic failover |
| `:single` | 1 | Development, non-critical |
| `:ha` | 3 (on separate physical machines) | Production, automatic failover |

**Legacy form** you may still see in older YAML: a separate `mode:` field — `mode: NON_HA` ≡ `:single`, `mode: HA` ≡ `:ha`. Still accepted (remapped to the variant) but deprecated and ignored by validation.

HA recovery: failed container is disconnected, new one created on different hardware, data synchronized from healthy copies, failed container removed.

Expand Down Expand Up @@ -155,7 +157,6 @@ services:
# Managed DB (vertical only, no container settings)
- hostname: db
type: postgresql:ha@16
profile: oltp-production
verticalAutoscaling:
cpuMode: DEDICATED
minCpu: 1
Expand Down
Loading