Managed Databases¶
How Starform provisions customer Postgres and Valkey.
- The customer-chosen DB tier alone decides the engine — billing plans (Hobby/Pro) never gate it.
- The bottom tier is a containerized throwaway instance living inside the project namespace; every tier above it is a dedicated DO Managed cluster.
- Customers pick tiers per environment (dev/staging/prod is their call); Starform warns on throwaway instances, it does not police.
(A synthesis page with no legacy § number. Design record: specs/2026-07-03-managed-db-topology-design.md.)
The DB tier ladder¶
Tier names reuse the Nova ladder (§1). The DO list cost column is a vendor constraint, not a sell price — customer pricing lives in the Financial Model (same rule as Depot §16.7 and Tigris §39.3 #16).
Postgres:
| Tier | Engine | Size | Base disk | DO list cost (constraint) |
|---|---|---|---|---|
| Mininova DB | Containerized throwaway (in-cluster pod) | 0.25 vCPU / 512 MiB | 1 GiB PVC | node slack + ~$0.11/mo block storage |
| Micronova DB | Dedicated DO Managed, single node | 1 GiB / 1 vCPU | 10–30 GiB | $15.15/mo |
| Nova DB | Dedicated DO Managed, single node | 2 GiB / 1 vCPU | 30–60 GiB | $30.45/mo |
| Supernova DB | Dedicated DO Managed, single node | 4 GiB / 2 vCPU | 60–120 GiB | $60.90/mo |
| Hypernova DB | Dedicated DO Managed, single node | 8 GiB / 4 vCPU | 140–280 GiB | $122.10/mo |
| Ultranova DB | Dedicated DO Managed, single node | 16 GiB / 6 vCPU | 290–580 GiB | $244.35/mo |
Valkey mirrors the same names 1:1 on DO's Valkey ladder — Mininova Valkey is a containerized
emptyDir cache (100m / 256 MiB); Micronova→Ultranova map to DO Managed Valkey 1/2/4/8/16 GiB
(DO list $15 / $30 / $60 / $120 / $240 per month). Extra managed storage is $0.215/GiB/mo on
either engine. DO's 32/64 GiB Valkey sizes stay unmapped until demand exists.
The throwaway contract (Mininova tier)
Mininova instances are not for production and the dashboard MUST say so (FR-074): no backups, no PITR, no upgrade or durability promises — data may be lost on node maintenance or volume failure, and deleting the entity deletes the data. That is the product: instant, ~free databases for previews, dev, and experiments. Best-effort nightly dumps are a seeded improvement (§39.3 #51).
Tier decides the engine¶
- Plans never gate. A Hobby-plan user can run an Ultranova DB; a Pro customer can run Mininova in dev. The plan is a billing construct (credit + usage, FR-055); the tier is an infrastructure choice (FR-074).
- Ephemeral environments are forced to Mininova. Preview/
is_ephemeralenvs (§24.1) always get throwaway instances — a dedicated cluster takes minutes to provision and churns real infrastructure for an environment that lives hours. A documented limitation, not a plan gate. - Databases are region-local (FR-078). A dedicated instance is VPC-private in its region; a Mininova instance is a pod on one cluster. Services in other regions cannot reach them privately (regions are never peered to each other), so the dashboard warns when a service is placed away from its environment's databases.
- Cross-boundary tier changes are blocked at MVP. Within the managed rungs (Micronova↔Ultranova) a tier change is a DO resize and works day one. Crossing Mininova→Micronova is a data migration — the promote-to-dedicated job is post-MVP (§39.3 #49); until then it means "create the new instance, move your data".
Mininova — the containerized throwaway engine¶
A Mininova database is a first-class desired-state citizen: Starbase emits it in the §25.1
databases array; Shuttle renders it like any workload. No new provisioning side-channel exists —
"Starbase decides, Shuttle applies" (§32) covers data too.
| Rendered resource | Spec |
|---|---|
| Deployment (1 replica) | Pinned image — postgres:16-alpine / valkey:8-alpine; resources 250m/512Mi (PG), 100m/256Mi (Valkey); starform.io/* labels incl. environment and database-id |
| Service (ClusterIP) | Stable in-namespace DNS for the app |
| PersistentVolumeClaim | Postgres only, 1 GiB (DO Block Storage CSI — self-installed on Talos at bootstrap). Valkey uses emptyDir — a cache is throwaway by definition |
| Secret (system) | Generated credentials + connection string, injected via envFrom like other system Secrets (§20.2) |
Because it is just a labeled pod, everything existing applies automatically: env-scoped NetworkPolicy isolation (§20.4), §25.4 status reporting, per-minute pod-snapshot billing (§36), and tombstone deletion with the delete breaker (§20.3) — deleting the entity deletes the PVC and the data, by design. This is the internal Mininova-DB PVC template only; customer-facing volumes remain post-MVP (§39.3 #7).
Micronova and above — dedicated DO Managed¶
- Provisioning: Starbase Worker →
DatabaseProviderport (§10) → DO API; async job, ~minutes; connection string and credentials land in the environment's system Secret through desired state — Shuttle never talks to the DO API. - Single node at MVP. DO supports +1/+2 standby nodes; the HA toggle is post-MVP (§39.3 #50). Within-managed resizes are DO resizes.
- Isolation — two layers (FR-075): DB-side,
the DatabaseProvider restricts network access to the hosting cluster's nodes — the DO
adapter's mechanism is Trusted Sources scoped to the cluster/node tag (cluster-granular
is DO's finest grain; pods SNAT to the node IP,
§4.4); other clouds use their firewall equivalent
(security groups / IP allowlists). Pod-side, a per-environment egress allowlist rendered by
Shuttle — the actual per-tenant boundary — so only the owning environment's pods may reach the DB
endpoint (an
ipBlockegress rule at MVP; the endpoint is off-cluster, CiliumtoFQDNis the later refinement, §20.4). Net effect: a leaked connection string still only ever exposes the one customer's own database.
Observability of database workloads¶
Mininova pods carry the standard starform.io/* label set minus service-id (a database is
not a service) plus starform.io/database-id (§24.1).
Their logs and cAdvisor series therefore attribute to project · environment · database rather
than the service tuple; wiring that attribution through the KSM allowlist and the SRE guide's
sync checklist is an MVP-blocking design item (§39.1 #54)
so the self-contained observability guide is not silently drifted by this page.
Table¶
databases (
id UUID PRIMARY KEY,
environment_id UUID NOT NULL REFERENCES environments(id) ON DELETE CASCADE,
name TEXT NOT NULL,
engine TEXT NOT NULL CHECK (engine IN ('postgres', 'valkey')),
tier TEXT NOT NULL, -- the tier decides the engine mode (above)
cluster_id UUID REFERENCES clusters(id), -- containerized (Mininova) placement
region_id TEXT REFERENCES regions(id), -- dedicated instances: region-local (FR-078)
provider_instance_id TEXT, -- cloud's ID (dedicated only)
endpoint TEXT, -- dedicated: private hostname (§25.1)
created_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ,
deletion_confirmed_at TIMESTAMPTZ, -- Shuttle tombstone ack (§25.4)
UNIQUE (environment_id, name)
);
API endpoints¶
Conventions (auth, errors, Developer* notation) →
Dashboard API.
| Method | Path | Permission | Purpose |
|---|---|---|---|
| GET / POST | /environments/{id}/databases |
Viewer / Developer* | List · create (engine, tier) |
| GET / DELETE | /databases/{id} |
Viewer / Developer* | Read · delete (tombstone — Mininova data dies with it, FR-074) |
| PATCH | /databases/{id} |
Developer* | Tier resize within managed rungs; Mininova↔Micronova boundary → 409 tier_boundary (§39.3 #49) |
| GET | /databases/{id}/credentials |
Developer* | Connection info; masked in protected envs below Proj Admin (§16.12) |
Quotas & the reseller partnership¶
DO's account soft-quotas (10 DB clusters by default) are lifted through the DO reseller partnership — they are administrative numbers, not architectural limits. The operational runbook — tracking per-region counts and requesting raises ahead of growth through the partnership channel — is §39.3 #47.
Deferred¶
Deferred beyond MVP
- Promote-to-dedicated (Mininova→Micronova dump/restore; the natural upgrade funnel) — §39.3 #49
- HA standby toggle on managed tiers — §39.3 #50
- Best-effort nightly
pg_dump→ DO Spaces for throwaway instances — §39.3 #51 - Shared multiplexed managed pools — rejected for MVP (out-of-band SQL provisioning side-channel, password-only isolation, per-region fixed floor, pool-wide blast radius); revisit only if throwaway data-loss churn materializes — §39.3 #52
Cross-references
Tier names → §1 · desired-state
databases array → §25.1 · rendered resources &
apply order → §20.2 /
§20.3 · labels →
§24.1 · billing mechanics →
§36 · VPC & Trusted Sources →
§4.4 · DatabaseProvider port →
§10 · FR-074/075/076 →
Functional Requirements. Canonical map:
Canonical Sources.