Family wealth management platform on Google Cloud. Cloud Run, Alpaca Broker API, PostgreSQL, event-driven architecture.
Why NOT start with Kubernetes — and why migrating is trivial when you need it.
xychart-beta
title "Monthly Cost: Cloud Run vs GKE Autopilot"
x-axis ["MVP 0-1K", "Growth 1-10K", "Scale 10-100K", "100K+"]
y-axis "USD / month" 0 --> 3500
bar [14, 120, 1400, 1400]
bar [274, 600, 2200, 2500]
line [14, 120, 1400, 1400]
line [274, 600, 2200, 2500]
| Factor | Cloud Run | GKE Autopilot |
|---|---|---|
| Management fee | $0 | $74/mo fixed |
| Compute MVP | ~$0 (free tier) | ~$200/mo min |
| Compute 100K users | ~$450/mo | ~$800-1,200/mo |
| Setup time | 2 hours | 1-2 weeks |
| Scale to zero | Yes | No |
| Platform engineers | 0 needed | 1-2 ($30K/mo) |
| Deploy command | gcloud run deploy | helm upgrade + kubectl |
| Blue/green deploys | Automatic | Argo Rollouts config |
| YAML files | 0 | 20-30 per service |
What you MUST have and what you DON'T. Every dollar and every hour counts as a solo dev.
Your API runs here. Free tier covers up to ~2M requests/month. One service is enough up to 10K users.
MVP: db-f1-micro ($8). Growth: db-custom-1-3840 HA ($50). Your data lives here.
UGMA/UTMA accounts, KYC, ACH, trading. They are your broker-dealer. Revenue share model.
Alpaca keys, JWT keys, DB password. Never hardcode secrets.
Test → Build → Deploy automatically on every push. CI/CD from day 1.
Docker images. Required for Cloud Run.
TestFlight + App Store. Required for iOS distribution.
Reviews terms, privacy policy, fintech disclosures. Do not launch without this.
Cloud Run does everything you need. 1 service is enough up to 10K.
Sessions in PostgreSQL. Rate limiting in memory. Redis is an optimization, not a requirement.
Only needed for Redis private IP. No Redis, no connector.
Rate limiting in app middleware. WAF is for when you have traffic worth attacking.
AES-256-GCM with key in Secret Manager is sufficient. CMEK is for SOC2 audits.
Direct gcloud CLI up to 10K. IaC when the team grows and config drift matters.
In-process EventBus (Go channels) until you extract services. Same interface.
A single PostgreSQL handles 10K users without issue. Add replica when dashboard queries impact latency.
Everything connected — from iOS app to Alpaca trade execution.
flowchart TB
IOS["iOS App"] & WEB["Web App"]
GLB["Global HTTPS LB · TLS 1.3"]
ARMOR["Cloud Armor WAF"]
IOS & WEB --> GLB --> ARMOR
subgraph VPC["GCP VPC — Private Network"]
direction TB
ARMOR --> API & WEBSERV
API["beaver-api\n25+ endpoints\nmin:2 max:100"]
WEBSERV["beaver-web"]
API -->|"publish"| TOPICS
WEBHOOK -->|"publish"| TOPICS
TOPICS["Pub/Sub Topics\naccount · transfer · trade\nnotification · rebalance · recurring"]
TOPICS -->|"subscribe"| WORKER & NOTIFIER
TOPICS -.->|"failed"| DLQ["Dead Letter Topics\nP1 alert"]
WORKER["beaver-worker\nTrades · Rebalance\nReconciliation"]
NOTIFIER["beaver-notifier\nPush · Email · SMS"]
SCHED["beaver-scheduler\nRecurring deposits\nDrift detection"]
SCHED -->|"publish"| TOPICS
API -->|"writes"| PRIMARY
API -->|"reads"| REPLICA
API <-->|"sessions · cache"| REDIS
WORKER -->|"writes"| PRIMARY
WORKER <-->|"locks"| REDIS
SCHED -->|"reads"| REPLICA
WEBHOOK -->|"dedup"| REDIS
PRIMARY[("Cloud SQL Primary\nPostgreSQL 16 HA\n4vCPU · 16GB · 100GB")]
REPLICA[("Read Replica\n2vCPU · 8GB")]
REDIS[("Redis 7 HA 2GB")]
end
API <-->|"accounts · trading"| ALPACA
API <-->|"bank link"| PLAID
WORKER -->|"trade exec"| ALPACA
ALPACA["Alpaca Broker API"] -->|"webhooks"| WEBHOOK
PLAID["Plaid"] -->|"webhooks"| WEBHOOK
P529["529 Provider"] -->|"webhooks"| WEBHOOK
PIRA["IRA Custodian"] -->|"webhooks"| WEBHOOK
WEBHOOK["beaver-webhook"]
NOTIFIER --> APNS["APNs"] & SG["SendGrid"] & TW["Twilio"]
API -.-> KMS["Cloud KMS"] & SECRETS["Secret Mgr"]
SCHED --> GCS["Cloud Storage\n7yr WORM audit"]
API -.-> OBS["Logging · Monitoring · Trace"]
CICD["GitHub Actions\nCanary deploys"] -.-> API & WORKER & WEBHOOK & NOTIFIER
style VPC fill:#f6f8fa,stroke:#d0d7de,stroke-width:2px
style TOPICS fill:#F39C12,stroke:#D68910,color:#000
style DLQ fill:#E74C3C,stroke:#C0392B,color:#fff
style API fill:#34A853,stroke:#1E7E34,color:#fff
style WEBSERV fill:#34A853,stroke:#1E7E34,color:#fff
style WORKER fill:#34A853,stroke:#1E7E34,color:#fff
style NOTIFIER fill:#34A853,stroke:#1E7E34,color:#fff
style SCHED fill:#34A853,stroke:#1E7E34,color:#fff
style WEBHOOK fill:#34A853,stroke:#1E7E34,color:#fff
style PRIMARY fill:#8E44AD,stroke:#6C3483,color:#fff
style REPLICA fill:#8E44AD,stroke:#6C3483,color:#fff
style REDIS fill:#8E44AD,stroke:#6C3483,color:#fff
style ALPACA fill:#5DADE2,stroke:#2E86C1,color:#fff
style PLAID fill:#5DADE2,stroke:#2E86C1,color:#fff
style P529 fill:#5DADE2,stroke:#2E86C1,color:#fff
style PIRA fill:#5DADE2,stroke:#2E86C1,color:#fff
style GLB fill:#E8913A,stroke:#B06D2B,color:#fff
style ARMOR fill:#E8913A,stroke:#B06D2B,color:#fff
style IOS fill:#4A90D9,stroke:#2C5F8A,color:#fff
style WEB fill:#4A90D9,stroke:#2C5F8A,color:#fff
style KMS fill:#566573,stroke:#2C3E50,color:#fff
style SECRETS fill:#566573,stroke:#2C3E50,color:#fff
style GCS fill:#566573,stroke:#2C3E50,color:#fff
style OBS fill:#566573,stroke:#2C3E50,color:#fff
style CICD fill:#2ECC71,stroke:#27AE60,color:#fff
style APNS fill:#AF7AC5,stroke:#8E44AD,color:#fff
style SG fill:#AF7AC5,stroke:#8E44AD,color:#fff
style TW fill:#AF7AC5,stroke:#8E44AD,color:#fff
6 independently deployable services. No Kubernetes needed.
Main HTTP API for the iOS app. 25+ endpoints. Handles auth, user management, fund creation, deposits.
Processes trades, portfolio rebalancing, reconciliation. CPU-intensive, isolated from API latency.
Ingests webhooks from Alpaca, Plaid, 529 provider, IRA custodian. Must respond <200ms.
Dispatches push notifications (APNs), email (SendGrid), SMS (Twilio). Different failure modes from API.
Cloud Run Job. Recurring deposits, drift detection, daily reconciliation, audit log export.
Landing page and future web app. Static serving via Cloud Run + Cloud CDN.
User taps "Add Money" → ACH transfer → auto-invest in ETFs → push notification.
sequenceDiagram
actor User as iOS User
participant API as beaver-api
participant ALP as Alpaca API
participant PS as Pub/Sub
participant WH as beaver-webhook
participant WK as beaver-worker
participant DB as Cloud SQL
participant RD as Redis
participant NT as beaver-notifier
User->>API: POST /transactions/deposit ($500)
API->>DB: Create pending transaction
API->>ALP: POST /transfers (ACH INCOMING)
ALP-->>API: transfer_id, QUEUED
API->>PS: publish transfer.initiated
API-->>User: 200 OK — deposit pending
Note over ALP: ACH processing (1-3 business days)
ALP->>WH: Webhook: transfer COMPLETE
WH->>RD: Dedup check (event_id)
WH->>DB: Log webhook
WH->>PS: publish transfer.completed
PS->>WK: subscribe: transfer.completed
WK->>RD: Acquire distributed lock (fund_id)
WK->>DB: Update transaction + create ledger entry
Note over WK: Auto-invest per fund allocation
WK->>ALP: Buy $300 VTI (60%)
WK->>ALP: Buy $150 VXUS (30%)
WK->>ALP: Buy $50 BND (10%)
WK->>RD: Release lock
WK->>PS: publish notification.send
PS->>NT: subscribe: notification.send
NT-->>User: Push: "$500 deposited and invested!"
Cloud SQL PostgreSQL 16 with HA, read replica, connection pooling, and schema separation.
flowchart TB
subgraph SERVICES["Cloud Run Services"]
API["beaver-api\nreads + writes"]
WORKER["beaver-worker\nwrites only"]
SCHED["beaver-scheduler\nreads only"]
end
subgraph POOL["PgBouncer Connection Pooling"]
PG1["Sidecar\npool=transaction\n10 conn/instance"]
PG2["Sidecar"]
PG3["Sidecar"]
end
subgraph CLOUDSQL["Cloud SQL PostgreSQL 16"]
PRIMARY[("PRIMARY — HA\n4 vCPU · 16GB · 100GB\nCMEK · PITR 30d")]
REPLICA[("READ REPLICA\n2 vCPU · 8GB\nlag less than 1s")]
PRIMARY -->|"async replication"| REPLICA
end
subgraph SCHEMAS["Database Schemas"]
PUB["public\nusers · funds · transactions\nledger_entries · beneficiaries"]
PII["pii\nuser_ssn · beneficiary_ssn\nrestricted access · audited"]
AUD["audit\naudit_log · webhook_log\nINSERT only"]
AN["analytics\nmaterialized views\ndaily aggregations"]
end
API --> PG1 --> PRIMARY
API -.-> REPLICA
WORKER --> PG2 --> PRIMARY
SCHED --> PG3 --> REPLICA
PRIMARY --- PUB & PII & AUD & AN
KMS["Cloud KMS"] -.->|"CMEK"| PRIMARY
GCS["Cloud Storage 7yr WORM"] -.->|"nightly export"| AUD
style PRIMARY fill:#8E44AD,stroke:#6C3483,color:#fff
style REPLICA fill:#8E44AD,stroke:#6C3483,color:#fff
style PII fill:#E74C3C,stroke:#C0392B,color:#fff
style AUD fill:#F39C12,stroke:#D68910,color:#000
style PUB fill:#34A853,stroke:#1E7E34,color:#fff
style AN fill:#5DADE2,stroke:#2E86C1,color:#fff
style KMS fill:#566573,stroke:#2C3E50,color:#fff
style GCS fill:#566573,stroke:#2C3E50,color:#fff
SOC2 Type II controls mapped to GCP services. FINRA/SEC compliance ready.
6 gates from push to production. Canary deploys with automatic rollback.
flowchart LR
subgraph G1["Gate 1: Quality"]
LINT["golangci-lint"] --> VET["go vet"] --> TEST["go test -race\ncoverage 80%+"]
end
subgraph G2["Gate 2: Security"]
VULN["govulncheck"] --> TRIVY["Trivy scan\nCRITICAL + HIGH"]
end
subgraph G3["Gate 3: Build"]
BUILD["Build 4 images\nin parallel"] --> AR["Push to\nArtifact Registry"]
end
subgraph G4["Gate 4: Staging"]
MIG["Migrations"] --> DEP["Deploy all\nservices"] --> E2E["E2E tests"]
end
subgraph G5["Gate 5: Canary"]
CAN["Canary deploy\n10% traffic"] --> SOAK["5-min soak\nmonitor errors"]
end
subgraph G6["Gate 6: Prod"]
APR["Manual\napproval"] --> MIGP["Migrations"] --> ROLL["Full\nrollout"]
end
PUSH["git push\nmain"] --> G1 & G2
G1 & G2 --> G3 --> G4 --> G5 --> G6
style PUSH fill:#4A90D9,stroke:#2C5F8A,color:#fff
style APR fill:#E74C3C,stroke:#C0392B,color:#fff
style ROLL fill:#34A853,stroke:#1E7E34,color:#fff
style E2E fill:#F39C12,stroke:#D68910,color:#000
style CAN fill:#F39C12,stroke:#D68910,color:#000
~$1,400/mo GCP infrastructure at 100K users. Less than 1% of total cost (team is 98%+).
| Service | Spec | Monthly |
|---|---|---|
| Cloud SQL Primary + Replica | 4vCPU 16GB HA + 2vCPU 8GB | $550 |
| Cloud Run (6 services) | auto-scaled, mixed min instances | $450 |
| Memorystore Redis | Standard HA, 2GB | $70 |
| VPC Connector | e2-medium x2 | $50 |
| Cloud Armor + Global LB | WAF rules + HTTPS LB | $40 |
| Logging + Monitoring + Trace | 50GB ingestion, custom metrics | $45 |
| Pub/Sub | ~2M messages/day | $15 |
| Cloud Storage | 50GB (audit, docs, backups) | $5 |
| KMS + Secrets + DNS | 3 keys, 20 secrets, 1 zone | $7 |
| Artifact Registry | ~5GB images | $1 |
| TOTAL GCP | ~$1,233 |
pie title Monthly GCP Cost Breakdown
"Cloud SQL" : 550
"Cloud Run" : 450
"Redis" : 70
"VPC + LB + Armor" : 90
"Observability" : 45
"Other" : 28
From $0/mo to $1,400/mo — scale infrastructure only when needed.
~$10-14/mo
~$100-125/mo
~$1,200-1,600/mo
$2,500+/mo
timeline
title Beaver Infrastructure Evolution
section Bootstrap
Solo founder : Cloud Run free tier
: Neon PostgreSQL free
: $0/mo
section MVP (1K users)
Solo founder : Cloud SQL micro
: Single Cloud Run service
: ~$14/mo
section Growth (10K users)
5-8 engineers : Add Redis + Cloud Armor
: Terraform IaC
: ~$120/mo
section Scale (100K users)
10-15 engineers : 6 Cloud Run services
: Pub/Sub event bus
: HA + Read replica
: SOC2 Type II
: ~$1,400/mo
section Next (500K+ users)
20+ engineers : Evaluate GKE
: Multi-region
: BigQuery + ML
: $2,500+/mo