AWS · Azure · GCP · OCI · all Terraform

One site, four clouds, one bill I publish.

This portfolio is not a screenshot of a multi-cloud diagram. It is served live by AWS, Azure, Google Cloud and Oracle Cloud, rotating between them every couple of days, each with its own AI chatbot, and with guardrails that keep the whole thing honest about cost.

Route 53 weighted DNS Health-check failover 4 LLM providers OIDC deploys Terraform GitOps FinOps guardrails
4clouds serving Same HTML on AWS, Azure, GCP and OCI.
60sDNS TTL A rotation or failover reaches visitors within a minute.
~90sto fail over Three failed probes pull a cloud out of DNS.
0portal clicks Every resource is Terraform, applied from pull requests.

The mechanism

A visitor asks DNS, and DNS picks the cloud

cloud.albaker.info has four weighted DNS records, one per cloud. Route 53 answers in proportion to the weights, so setting one cloud to 100 and the rest to 0 sends every new visitor there. Each cloud also keeps a permanent name of its own (azure., gcp., oci.albaker.info), so any one of them can be checked directly at any time.

Visitor browser Route 53 4 weighted records TTL 60s health checks pull a failing cloud out AWS S3 + CloudFront · Lambda · Bedrock (Claude) · DynamoDB Azure Static Web Apps · Functions · Azure OpenAI · Cosmos DB Google Cloud Firebase Hosting · Cloud Run functions · Gemini · Firestore Oracle Cloud Object Storage + API Gateway · Functions · Grok · NoSQL
Same page, same chatbot persona, four completely different stacks underneath. Only the cloud badge and the model change, and that difference is the point: the frontend is decoupled from every provider behind it.

The rotation

Every cloud takes a turn, on a schedule in code

MondayAWS
WednesdayAzure
FridayGCP
SundayOCI

A scheduled GitHub Actions workflow flips the weights at 00:00 UTC on those days. It changes only the four DNS records, nothing else, and sends an alert for every rotation. A manual run can point all traffic at any one cloud in under a minute, which doubles as a disaster-recovery drill.

  1. Why 60 seconds

    DNS caching is the enemy of active/active. A one-minute TTL means a flipped weight is fully live within a minute. The cost is a few more DNS queries, which at this traffic is pennies.

  2. Why every couple of days, not hourly

    Each cloud holds traffic long enough for browser and CDN caches to warm, so a returning visitor sees a consistent site instead of a different cloud on every click.

  3. What happens when a cloud fails

    HTTPS health checks probe each cloud every 30 seconds. Three failures in a row and Route 53 stops answering with that cloud, whatever its weight, so the others absorb traffic in about 90 seconds with no one touching anything.

Honest gap

AWS, Azure and Google Cloud have health-check failover today. Oracle Cloud does not yet, so an OCI outage during OCI's turn would need a manual flip. Adding its probe is next on the list.

Same page, four stacks

Each layer, mapped across the four clouds

LayerAWSAzureGoogle CloudOracle Cloud
Hosting + CDNS3 (private) + CloudFrontStatic Web AppsFirebase HostingObject Storage + API Gateway
TLSACM wildcardManaged by SWAManaged by FirebaseLet’s Encrypt via Terraform
Chatbot computeLambdaSWA managed FunctionsCloud Run functionsOCI Functions
Language modelBedrock · Claude SonnetAzure OpenAI · GPT-4o miniVertex AI · Gemini 2.5 FlashGenerative AI · xAI Grok
Session + limitsDynamoDBCosmos DB serverlessFirestoreNoSQL Database
CI identityOIDC roleOIDC federationWorkload IdentityScoped API user

The chatbot keeps a short conversation history per browser tab, stored on the cloud that is serving it, expired after an hour, and never shared between visitors. Each provider wants messages in a different shape, so each function converts at the point it calls the model and stores one common format.

Guardrails

Secure by default, and capped so it cannot surprise me

No stored keys

Deploys to AWS, Azure and GCP use short-lived OIDC tokens from GitHub Actions. OCI uses a tightly scoped API user, not an admin key.

Least privilege

Plan jobs are read-only. Apply jobs cannot change their own permissions. Changing what CI may do is always a reviewed, local apply.

Detect and contain

GuardDuty threat detection and IAM Access Analyzer are on, and the AWS account refuses API calls outside its one region, so a leaked credential cannot quietly build elsewhere.

Hardened edge

HSTS, anti-framing and a content-security policy on AWS, Azure and GCP; OCI’s gateway is next. Geo-restriction is enforced at the CDN edge on AWS; the other three run it in the function, in log mode while the lookups are validated, because their free tiers have no edge option.

Chatbot caps

Per-visitor and daily limits on every chatbot. If the counter cannot be read, the request is refused: a briefly unavailable chat costs nothing, an unbounded one costs real money.

Spend brake

Budgets with alerts on every cloud. On AWS, crossing the hard limit automatically applies a policy that stops new paid activity, without waiting for me to read an email.

Delivered as code

Pull request in, infrastructure out

  1. Plan on every pull request

    Terraform plans each changed cloud and posts a summary of what would be added, changed or destroyed, so a reviewer reads the infrastructure change next to the code change.

  2. Apply on merge

    Merging applies the plan made on main, never a stale one from the branch. One apply per cloud at a time, so two merges cannot race each other. The DNS stack and OCI apply through a deliberate manual step instead, because a mistake there takes the whole site down.

  3. A destroy needs a human

    Any plan that would delete or replace a resource stops until the pull request carries an explicit label. Routine changes flow; destructive ones need a decision.

  4. Merged is not deployed

    A smoke test after each deploy checks real responses, not just status codes, and an independent health check fails loudly if the monitoring itself goes quiet.

Trade-offs

What I chose not to buy, and when I would

Free tiers first

Azure Front Door or a Google load balancer with Cloud Armor would add edge security on those clouds, for tens to hundreds of dollars a month. At portfolio traffic, the function-level check gives the same protection for $0. With real customers, I would buy the edge.

DNS, not a global load balancer

Weighted DNS with health checks is cheap and transparent. Its limit is client caching; a production system with strict failover targets would put an anycast front door ahead of it.

The bill

Most multi-cloud claims hand-wave the cost. This one publishes it.

A nightly job pulls each cloud’s spend into a public dashboard. Publishing the real number is a small act of FinOps practice and a forcing function: any line that grows has to justify itself in public.

See the live cost dashboard

Next step

Want this kind of design for your platform?

Multi-cloud that actually fails over, CI that cannot grant itself more power, and a bill that never surprises anyone. I build and run this one myself, and it is all Terraform you can read in a pull request.

Start a conversation See the AgentCore platform