Skip to content

Ports Detail (Swappable Per Region)

Ports define what Starbase needs from cloud infrastructure. Each region maps to one implementation of each port. Swapping clouds means writing new adapters, not changing core logic.

Port Interface What It Abstracts MVP Adapter Future Adapters
ClusterProvider Customer-cluster lifecycle: create, delete, scale, get status Self-managed Talos on DO droplets (godo for droplets; MVP manual talosctl, post-MVP Shipyard) Talos on AWS EC2 / GCP GCE (plain VMs — the adapter targets self-managed Talos, not managed EKS/GKE, which can't expose the gVisor RuntimeClass, FR-082)
DatabaseProvider Dedicated managed DB tiers (Micronova+): create, resize, backups, PITR, connection strings, and DB-side network scoping to the hosting cluster's nodes (FR-075 — DO: Trusted Sources by tag; others: security groups / IP allowlists). Mininova throwaway instances flow through desired state (Shuttle-rendered pods), not this port (Managed Databases) DO Managed Postgres AWS RDS, GCP Cloud SQL
CacheProvider Managed cache: create, resize, connection strings DO Managed Valkey AWS ElastiCache, GCP Memorystore
RegistryProvider Container images: create repo, push/pull credentials, list tags — one registry instance per region (the Region struct binds it, §12); builds push to the placement region's registry (§16.2) DO Container Registry (per region) AWS ECR, GCP Artifact Registry
StorageProvider Object storage: create isolated tenant org, provision bucket, generate per-customer credentials, revoke on offboarding Tigris (Partner Integration API) AWS S3, GCP GCS, Cloudflare R2
DNSProvider DNS records: create, update, delete A/CNAME records Cloudflare Cloudflare (unchanged across clouds)
PaymentProvider Billing: create customer, create subscription, usage reporting, invoices Stripe Stripe (unchanged)
BuildService Build execution: framework detection, submit build, poll status, get image reference, stream logs Depot SaaS + Railpack (primary) + Dockerfile (fallback) Self-hosted BuildKit, AWS CodeBuild
JobQueue Async jobs: enqueue, dequeue, ack, retry Postgres table (MVP) RabbitMQ (scale)

Wiring example in cmd/api/main.go:

Region wiring · cmd/api/main.go
regions := region.NewRegistry()
regions.Register("nyc3", region.Config{
    Cloud:    "digitalocean",
    Cluster:  digitalocean.NewClusterAdapter(doClient),
    Database: digitalocean.NewDatabaseAdapter(doClient),
    Cache:    digitalocean.NewCacheAdapter(doClient),
    Registry: digitalocean.NewRegistryAdapter(doClient),
    Storage:  tigris.NewStorageAdapter(tigrisClient),  // Partner Integration API
})

// Core uses ports — doesn't know about DO
deploySvc := deploy.NewService(regions, store, queue)

Adding AWS later means writing adapter/aws/*.go and registering a new region. Zero changes to core.


Cross-references

Where adapters live in the tree → §9 · integrations (the other pattern — all active at once) → §11 · the Region struct that binds a port set → §12 · the BuildService port's full contract → Starforge §16.3.