Skip to content

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_ephemeral envs (§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 → DatabaseProvider port (§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 ipBlock egress rule at MVP; the endpoint is off-cluster, Cilium toFQDN is 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 · customer DB/cache entities · Starbase Postgres — created_at→deleted_at doubles as the FR-076 metering ledger
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.