All posts
Cloud Engineering5 min read

Cloud Engineering for Government: What We've Learned Running AWS, Azure and GCP Side by Side

Data sovereignty, procurement frameworks and a decade of public-sector engagements — here's what actually matters when your workloads span AWS, Azure and Google Cloud.

Pardeep Basi

Founder, Basi Software Ltd

About the author

Pardeep Singh Basi is a senior full-stack TypeScript/JavaScript engineer trading as Basi Software Ltd. With 18+ years of experience - the last seven delivering exclusively for UK government departments - he specialises in Node.js, React, SvelteKit, Angular and cloud-native infrastructure on Azure, AWS and GCP.

#cloud#AWS#Azure#GCP#kubernetes#public sector
Illustrated diagram showing AWS, Azure and Google Cloud nodes connecting into a shared Kubernetes and security layer, representing multi-cloud architecture

“Multi-cloud” gets sold as a strategy. It usually isn’t one — it’s a consequence. A department already has an Azure tenancy from its M365 estate, a delivery partner built the last service on AWS, and a data science team wants BigQuery. Nobody planned this. Somebody has to run it anyway.

After a decade architecting platforms across AWS, Azure and Google Cloud for public-sector clients, here’s what actually matters once you’re past the “which cloud is best” debate and into keeping production workloads secure, compliant and affordable.

1. Sovereignty and classification come before architecture

On commercial projects, region selection is a performance decision. On government projects, it’s a legal one first.

Before a single Terraform module gets written, we settle:

  • What classification does this data carry — OFFICIAL, OFFICIAL-SENSITIVE, or higher?
  • Which region(s) satisfy the residency requirement, and does the provider’s shared-responsibility model actually meet it, or just claim to?
  • Who holds the encryption keys — the provider, or does the engagement require customer-managed keys (CMK/BYOK)?
# Encryption key ownership is a decision, not a default
resource "aws_kms_key" "official_sensitive" {
  description             = "CMK for OFFICIAL-SENSITIVE workloads"
  deletion_window_in_days = 30
  policy                  = data.aws_iam_policy_document.key_admins.json
  # Key never leaves customer control — no provider-managed fallback
}

Get this wrong and no amount of good engineering fixes it later. We’ve seen migrations paused for months because data residency was assumed rather than verified.

2. Pick the right cloud per workload, not one cloud for everything

The teams that struggle with multi-cloud are the ones trying to make every workload portable everywhere. The teams that succeed pick a primary provider per workload based on what it’s actually good at, and standardise the seams between them.

WorkloadWhere we typically land itWhy
GOV.UK-style citizen servicesAWS GovCloud / UK regionsMature PaaS ecosystem, established public-sector accreditation
M365-integrated case managementAzureNative AD, Graph API, existing tenancy
Data platforms & analyticsGCPBigQuery cost model, strong data tooling
Container workloadsWhichever region residency demandsPortable by design — see below

The mistake isn’t using three clouds. It’s using three clouds without deciding why for each one.

3. Kubernetes is the only thing that makes multi-cloud bearable

Compute, IAM and networking APIs differ across AWS, Azure and GCP in ways that never fully abstract away. Kubernetes is the closest thing to a common substrate, and it’s the one investment that pays off regardless of which providers you end up running.

# Same manifest, three managed control planes
# EKS, AKS and GKE all accept this without modification
apiVersion: apps/v1
kind: Deployment
metadata:
  name: claims-api
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: claims-api
          image: registry.internal/claims-api:1.4.2
          resources:
            requests: { cpu: "250m", memory: "256Mi" }
            limits:   { cpu: "500m", memory: "512Mi" }

We still run provider-native services underneath — RDS, Cosmos DB, Cloud SQL — because reimplementing managed databases on Kubernetes is rarely worth it. But the application layer stays portable, and that portability is what lets a department move a workload when a framework contract changes.

4. FinOps is a weekly habit, not an annual review

Cloud cost overruns in the public sector rarely come from one bad decision. They come from nobody looking until the invoice lands on a director’s desk.

# What an unmanaged multi-cloud bill actually looks like after 12 months
AWS:   forecast £18k/mo actual £31k/mo  (orphaned EBS volumes, over-provisioned RDS)
Azure: forecast £9k/mo actual £14k/mo  (dev/test resources never torn down)
GCP:   forecast £4k/mo actual £4.2k/mo (tagged and budget-alerted from day one)

The GCP line is the outlier for a reason — it had budget alerts and mandatory tagging enforced by policy from launch. The other two didn’t, until we added it.

# Tag enforcement at the policy layer, not the honour system
resource "aws_organizations_policy" "require_cost_tags" {
  content = jsonencode({
    tags = {
      "cost-centre" = { tag_key = { "@@assign" = "cost-centre" }, enforced_for = { "@@assign" = ["ec2:instance", "rds:db"] } }
    }
  })
}

Tag enforcement, budget alerts and a weekly cost review are the difference between a forecast and a fantasy.

5. Infrastructure as code is the single source of truth — or it’s nothing

Multi-cloud without IaC means three consoles, three sets of tribal knowledge, and a change history that lives in nobody’s head after they leave. Terraform (or OpenTofu) with per-provider modules behind a shared interface is what makes audits survivable.

module "network" {
  source   = "./modules/network/${var.cloud_provider}"
  cidr     = var.network_cidr
  env      = var.environment
}

Every change goes through the same PR review, the same plan-before-apply gate, the same audit trail — regardless of which cloud it targets. That consistency matters more to an ISO 27001 or Cyber Essentials Plus auditor than which provider you picked.

Key takeaways

  • Classify before you architect — sovereignty and key ownership are legal decisions, not infrastructure ones
  • Choose deliberately per workload — multi-cloud by accident is a liability; multi-cloud by design is a strength
  • Kubernetes is the portability layer — invest there, not in chasing full cloud-agnosticism everywhere
  • FinOps is continuous — tag enforcement and budget alerts beat a quarterly spreadsheet every time
  • IaC is your audit trail — if it’s not in code and reviewed, it didn’t happen

Multi-cloud isn’t inherently a good or bad strategy. It’s a set of constraints somebody else already handed you. The engineering job is making those constraints boring — predictable, auditable, and cheap to run.

Comments

Loading comments…

Your email will not be published.

Ready to start?

Let's build something
exceptional together

Whether you're a government body looking for a trusted supplier, or a business seeking a design-forward engineering partner — we'd love to hear from you.