:: clouds_mapped
scope beginner → working mental modelsnapshot 2026-08-03
Technical field guide / AWS · Azure · Google Cloud · Databricks

Clouds,
mapped.

A beginner’s guide to how cloud platforms are shaped, how their services correspond, how permissions actually flow, and how to put one small working system on each.

04 platformsthree clouds + one data platform
27 capabilitiesparallel service atlas
04 build labscompute + storage + identity
~90 min readreference, not memorisation
00 Orientation

Start with the shape, not the product catalogue.

AWS, Azure, and Google Cloud are general-purpose infrastructure clouds. Databricks usually runs on one of them and specialises in data engineering, analytics, governance, and AI. Treating all four as peers is the first mistake this guide will prevent.

The one sentence to remember

A human identity creates a resource; a workload identity runs the code; a policy connects that identity to exactly the data it may use; region and network rules decide whether the request can physically reach it.

AWS

The broadest toolbox

Boundary: the AWS account. Style: many focused services, explicit JSON policies, regional resources, very mature infrastructure primitives.

Strong default when job listings are broad, infrastructure depth matters, or you want the largest ecosystem.

Azure

The enterprise estate

Boundary: the subscription, under a Microsoft Entra tenant. Style: resource groups, Azure RBAC, strong Microsoft and hybrid integration.

Natural when the organisation already lives in Microsoft identity, data, developer, or endpoint tooling.

Google Cloud

The project-centric cloud

Boundary: the project. Style: global VPCs, relatively opinionated services, strong containers, serverless, data, and ML.

Especially legible for cloud-native applications, Kubernetes, analytics, and teams that value a smaller core vocabulary.

Databricks

The governed data plane

Boundary: workspace access plus Unity Catalog privileges. Style: Spark/Photon compute over lakehouse data, SQL, workflows, ML, and AI.

Learn it for data engineering, analytics, ML platforms, and lakehouse work—not as a substitute for all cloud infrastructure.

Pick one home cloud; learn the mappings second

A beginner becomes useful faster by building the same small system repeatedly on one platform, then translating it. If you already have some Azure exposure, deepen Azure until identity, networking, storage, deployment, and logs feel routine. Then use this map to acquire AWS and GCP vocabulary without relearning distributed systems from zero.

Cost rule zero

Create a budget alert before compute. Alerts are generally not hard caps, billing data can lag, and deleting application code does not delete deployed resources. Every lab below ends with an explicit teardown.

01 Platform topology

Where does a resource live?

Every cloud has two overlapping maps: an administrative hierarchy for ownership, policy, and billing; and a physical scope for region, zone, and network. A database can inherit permission from its administrative ancestors while still being unreachable because of its physical network.

Organisationgovernance root
Work boundaryaccount / subscription / project
Regiondata locality
Networkroute + firewall
Servicecompute / storage
Data objectblob / row / message
Telemetrylogs + cost
AWS administrative tree
  1. AWS Organization central billing and guardrails
  2. Organizational Unit (OU) group accounts; inherit SCPs
  3. AWS account primary isolation and quota boundary
  4. Region → VPC → subnet/AZ physical and network placement
  5. Resource identified by ARN for example Lambda function or S3 bucket
Azure administrative tree
  1. Microsoft Entra tenant identity directory; not the bill itself
  2. Management group subscription policy and RBAC inheritance
  3. Subscription billing, quota, and policy boundary
  4. Resource group lifecycle container for related resources
  5. Resource ARM resource ID; may expose separate data plane
Google Cloud administrative tree
  1. Organization usually backed by Cloud Identity / Workspace
  2. Folder optional policy and team grouping
  3. Project trust, API, quota, and common billing unit
  4. Global / region / zone scope varies by resource type
  5. Service resource bucket, Cloud Run service, VM, dataset
Databricks administrative + data tree
  1. Databricks account subscription, identities, workspaces
  2. Workspace ↔ Unity Catalog metastore working surface linked to regional governance
  3. Catalog top namespace for a domain or environment
  4. Schema project/use-case grouping
  5. Table / view / volume / model securable data and AI object

The closest boundary translations

Concept
AWS
Azure
Google Cloud
Databricks
Company root
Organization
Entra tenant + root management group
Organization
Databricks account
Workload isolation
Account
Subscription
Project
Workspace plus catalog boundaries
Lifecycle group
CloudFormation stack / tags
Resource group
Project / labels
Bundle / catalog / schema
Resource identity
ARN
ARM resource ID
Full resource name
Workspace ID or three-part name

These are working analogies, not exact equivalences. Most importantly, an Azure resource group has no exact AWS equivalent, and a Databricks workspace does not replace its host cloud account/subscription/project.

02 Parallel service atlas

Same capability, different product grammar.

Use this as a translation index, not a procurement decision. Rows mean “solves a related class of problem,” not “feature-for-feature equivalent.” Databricks cells are intentionally blank where the platform expects its host cloud to provide the primitive.

27 capability rows
CapabilityAWSAzureGoogle CloudDatabricksWhat it is for
Organisation guardrailsOrganizations, Control Tower, SCPsManagement Groups, Azure Policy, Landing ZonesResource Manager, Organization PolicyAccount console, workspace bindings, Unity CatalogApply governance above individual workloads.
Human identityIAM Identity Center; federated rolesMicrosoft Entra IDCloud Identity / Google Workspace + IAMFederated account identities; groupsAuthenticate workforce users without personal access keys.
Workload identityIAM role + STSManaged identity or service principalService account; Workload Identity FederationService principal; job run identityGive running code short-lived credentials.
Virtual machinesEC2Azure Virtual MachinesCompute EngineHost-cloud classic compute under the hoodMaximum OS control; maximum operations burden.
Autoscaled VM fleetEC2 Auto ScalingVirtual Machine Scale SetsManaged Instance GroupsManaged by Databricks computeReplicated VM instances behind health checks.
FunctionsLambdaAzure FunctionsCloud Run functionsNotebook / Python / SQL tasks are not general functionsShort event-driven code with little server management.
Serverless containers / webApp Runner; ECS on FargateContainer Apps; App ServiceCloud RunDatabricks Apps data/AI apps, narrower purposeRun an HTTP container without managing a VM fleet.
KubernetesEKSAKSGKENot a Kubernetes control planePortable container orchestration when you need its ecosystem/control.
Batch computeAWS BatchAzure BatchBatchLakeflow JobsQueued, retryable, finite workloads.
Object storageS3Blob Storage / ADLS Gen2Cloud StorageUnity Catalog volumes and tables over cloud object storageCheap, durable blobs/files addressed by keys.
Block storageEBSManaged DisksPersistent Disk / HyperdiskEphemeral/local compute storage onlyA virtual disk attached to compute.
Shared file storageEFS; FSxAzure Files; Azure NetApp FilesFilestore; NetApp VolumesVolumes expose file paths, but are object-backedShared filesystem semantics such as NFS/SMB.
Managed relational DBRDS; AuroraAzure SQL Database; Azure Database for PostgreSQLCloud SQL; AlloyDB; SpannerLakebase PostgresTransactional rows, constraints, indexes, and SQL.
Document / key-value DBDynamoDB; DocumentDBCosmos DBFirestore; BigtableDelta tables are analytical, not a drop-in OLTP storeLow-latency application state at high scale.
Managed cacheElastiCache; MemoryDBAzure Managed RedisMemorystoreUse host cloud or Lakebase cache patternsVery low-latency transient data.
Queue / pub-subSQS; SNS; EventBridgeService Bus; Event GridPub/Sub; EventarcLakeflow Jobs task dependencies not a general message busDecouple producers and consumers; absorb spikes.
Event streamingKinesis; MSKEvent HubsPub/Sub; Managed Service for Apache KafkaStructured Streaming; Lakeflow pipelinesContinuously ingest and process ordered event flows.
API gatewayAPI GatewayAPI ManagementAPI Gateway; ApigeePut a cloud/API gateway in front of an app or serving endpointAuthentication, quotas, routing, versions, and developer access.
Data integration / ETLGlue; EMR; MWAA; Step FunctionsData Factory; Fabric Data FactoryDataflow; Dataproc; Cloud ComposerLakeflow Connect, Jobs, and pipelinesIngest, transform, schedule, and observe data movement.
Data warehouseRedshift; AthenaFabric Warehouse; Synapse AnalyticsBigQueryDatabricks SQL warehousesColumnar analytical SQL across large datasets.
Lakehouse governanceLake Formation; Glue Data Catalog; DataZoneMicrosoft Purview; Fabric / Databricks governanceBigLake; Dataplex Universal CatalogUnity CatalogDiscover, secure, audit, and trace data/AI assets.
AI / ML platformBedrock; SageMaker AIMicrosoft Foundry; Azure Machine LearningVertex AIMosaic AI; MLflow; Model ServingBuild, evaluate, govern, and serve models and agents.
Secrets and keysSecrets Manager; KMS; Parameter StoreKey Vault; App ConfigurationSecret Manager; Cloud KMSSecret scopes; service credentialsKeep credentials and encryption keys out of code/config files.
Logs / metrics / tracesCloudWatch; X-RayAzure Monitor; Application InsightsCloud Logging; Monitoring; TraceSystem tables; query history; job/pipeline observabilityKnow what happened, how long it took, and why it failed.
Audit trailCloudTrailAzure Activity LogCloud Audit LogsAudit logs; system.access.auditRecord control-plane and selected data-plane actions.
Infrastructure as codeCloudFormation; CDK; SAM; TerraformBicep / ARM; azd; TerraformTerraform; Infrastructure Manager; Config ConnectorTerraform provider; Declarative Automation BundlesVersion, review, reproduce, and delete environments.
Cost managementCost Explorer; Budgets; CURCost Management; budgets; exportsCloud Billing; budgets; billing exportAccount budgets; usage policies; system.billing.usageAttribute spend and catch anomalies before invoices surprise you.

There are often several valid matches because clouds split products at different seams. Example: an “API backend” might be Lambda + API Gateway on AWS, one Azure Function, a Cloud Run service on GCP, or a Databricks App backed by Lakebase for a data-centric internal tool.

03 Regions, networks, and data

The foundations beneath every service name.

Regions and zones are failure boundaries

A region is a separate geographic area. A zone is an isolated datacenter group inside a region. Multi-zone protects against a zonal failure; multi-region protects against larger failures and may satisfy residency or latency requirements. It also costs more and introduces replication choices.

Choose region by

Data residency and compliance → service availability → user/data latency → price → carbon and organisational standards. “Nearest” is only one input.

Know resource scope

A resource can be global, regional, or zonal. A zonal VM disk cannot simply attach across zones. A globally named bucket still stores data in selected location(s).

Design explicitly

Some managed services replicate across zones automatically; others require multiple instances. Read the service’s reliability guide, not just the region marketing page.

The network difference worth memorising

Primitive
AWS
Azure
Google Cloud
Databricks
Private network
VPC is regional
VNet is regional
VPC is global
Serverless networking or classic compute in host-cloud network
Subnet
Scoped to one AZ
Regional; spans zones
Regional; spans zones
Configured through the chosen deployment model
Firewall identity
Security groups on interfaces; NACLs on subnets
NSGs on subnet/NIC
VPC firewall policies/rules, often target tags or service accounts
Workspace controls + host-cloud security controls
Private PaaS access
VPC endpoints / PrivateLink
Private Endpoint / Private Link
Private Service Connect / Private Google Access
Private connectivity varies by cloud and serverless/classic plane

This is why copied diagrams fail: an AWS “one subnet per AZ” pattern should not be transplanted literally into Azure or GCP.

Control plane versus data plane

Control planeCreate, configure, tag, scale, or delete the storage account/bucket/database. Usually addressed through the provider’s resource manager API.
Data planeRead a blob, insert a row, publish a message, invoke a model. Often a different endpoint with different roles and sometimes different network rules.
Runtime planeThe compute identity, environment variables, deployed code, scaling configuration, and network path used while the application runs.
Classic Azure trap

Contributor can manage a Storage Account but does not automatically grant Blob data access through Microsoft Entra ID. Add a data role such as Storage Blob Data Contributor at the narrowest useful scope.

Choose a data model before a database brand

ModelThink of it asGood forBad fit
Object storageA huge key → bytes map. “Folders” are usually key prefixes.Files, media, backups, logs, data lakes, static assets.In-place row updates, filesystem locking, low-latency transactions.
Block storageA virtual disk attached to a machine; you add a filesystem.VM boot/data disks, databases needing disk semantics.Direct browser access or effortless multi-host sharing.
Shared fileA managed NFS/SMB-like filesystem.Lift-and-shift software, shared working directories.Massive cheap lake storage or internet-scale object delivery.
Relational / OLTPRows, schemas, constraints, indexes, transactions.Orders, accounts, inventories, application state.Petabyte scans of immutable history without specialised design.
Key-value / documentA lookup by key with a flexible value/document.Profiles, sessions, carts, high-scale predictable access.Arbitrary joins and ad-hoc relational analytics.
Warehouse / lakehouseColumnar history optimised for scans; compute often separated from storage.BI, ETL, metrics, ML training sets, large analytical joins.Per-request transactional updates for a busy web application.
Queue / streamAn ordered or partitioned flow of messages/events.Decoupling, retries, buffering, event-driven systems.Canonical queryable state unless paired with storage.
04 Identity and permissions

Who is asking to do what, to which resource?

Cloud permission systems become less mysterious when every request is written as a sentence: principal P wants action A on resource R under conditions C. Authentication proves P. Authorisation evaluates policies. Networking still decides whether P can reach R.

Principalhuman or workload
Credentialprefer short-lived token
ActionPutObject / read blob
Resourceexact ARN / ID / name
Policiesallow, deny, inheritance
NetworkDNS, route, firewall
Decisionallow + audit event
AWS evaluation

Roles, policies, and trust

An IAM role has a trust policy saying who may assume it and permission policies saying what the resulting session may do. Identity policies and resource policies can grant access; permission boundaries, session policies, SCPs/RCPs, and explicit denies constrain it. An applicable explicit deny wins.

Azure evaluation

Principal + role + scope

A role assignment joins a security principal, role definition, and scope. It inherits downward through management group → subscription → resource group → resource. Microsoft Entra directory roles and Azure resource RBAC are separate systems. Managed identity is the workload principal.

Google Cloud evaluation

Member + role + resource

An allow policy binds a member (user, group, service account, or federated principal) to a role on a resource. Grants inherit from organization/folder/project to children. Deny policies and principal access boundaries can constrain access. The runtime should use a dedicated service account.

Databricks evaluation

Workspace access ≠ data access

A user or service principal first needs assignment/entitlement to the workspace, then privileges on compute and Unity Catalog securables. To query catalog.schema.table, the principal usually needs USE CATALOG, USE SCHEMA, and SELECT.

The identity choreography for an application

  1. Your human/federated identity signs in to the CLI. Avoid root users and long-lived access keys.
  2. Your deployment identity creates compute, storage, logs, and a runtime identity. Creating role assignments is often a separate privilege.
  3. A narrow policy grants the runtime identity only required actions on the precise data path.
  4. The platform injects short-lived credentials or exposes a metadata/token endpoint to the workload.
  5. The SDK’s default credential chain obtains and refreshes tokens. No secret is committed to source.
  6. The target service evaluates permission, conditions, public-access controls, and network policy; audit systems record the call.

A 403 / AccessDenied debugging ladder

01 · identity

Print the current caller: aws sts get-caller-identity, az account show, or gcloud auth list. In runtime logs, confirm the expected workload identity.

02 · target

Confirm account/subscription/project, region, full resource name, and object prefix. Many “permission” failures are wrong-environment failures.

03 · action

Find the exact rejected API action in the error or audit log. “Read storage” might require list on the container plus get on each object.

04 · grants

Inspect direct and inherited identity roles, resource policies, trust relationships, and parent privileges. Wait briefly after a new assignment if propagation is documented.

05 · guardrails

Check explicit denies, SCP/organization/Azure policies, permission boundaries, public-access prevention, and Databricks workspace bindings.

06 · network

Resolve DNS, inspect route/firewall/private-endpoint rules, and test from the workload’s network—not only your laptop.

Least privilege that stays operable

Grant groups, not individual humans; grant workloads their own identity; scope data access narrowly; keep deployer and runtime roles separate; record why every broad permission exists; and prefer temporary elevation for administration.

05 Object storage, end to end

What “create a bucket” actually means.

Object storage is the common first primitive because it exposes every important cloud concept at once: administrative scope, region, global naming, data model, encryption, public access, runtime identity, and a separate data endpoint.

Layer
AWS S3
Azure Blob
Cloud Storage
Unity Catalog volume
Admin parent
AWS account
Subscription → resource group
Project
Metastore → catalog → schema
Container
Bucket
Storage account → blob service → container
Bucket
Managed or external volume
Item
Object key
Blob name
Object name
File path under /Volumes/…
Permission
IAM + bucket policy + guardrails
Azure data RBAC / ABAC; optional ACLs with ADLS
IAM; prefer uniform bucket access
USE parents + READ/WRITE VOLUME

AWS: private S3 bucket

Bucket names are globally unique, but the bucket lives in one selected region. New buckets default to Bucket owner enforced object ownership (ACLs disabled) and no public access; retain Block Public Access unless public object hosting is truly intended.

# Use a globally unique lowercase name; keep your chosen region explicit.
REGION="ap-southeast-2"
BUCKET="cloud-lab-$RANDOM-$RANDOM"

aws sts get-caller-identity
aws s3 mb "s3://$BUCKET" --region "$REGION"
aws s3api put-public-access-block --bucket "$BUCKET" \
  --public-access-block-configuration \
  'BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true'

printf '{"hello":"aws"}' | aws s3 cp - "s3://$BUCKET/hello.json"
aws s3api head-object --bucket "$BUCKET" --key hello.json

The CLI is acting as your current human/federated principal. A Lambda function should not reuse that identity; it assumes its own execution role with permission such as s3:PutObject on arn:aws:s3:::bucket/prefix/*.

Azure: private blob container

Azure adds a wrapper: the globally unique Storage Account hosts Blob, Queue, Table, and File services. A blob path is https://account.blob.core.windows.net/container/blob. Control-plane Contributor rights do not by themselves grant OAuth data access.

RG="cloud-storage-lab"
REGION="australiaeast"
STORAGE="cloudlab$RANDOM$RANDOM" # 3–24 lowercase letters/digits

az account show --output table
az group create --name "$RG" --location "$REGION"
az storage account create --name "$STORAGE" --resource-group "$RG" \
  --location "$REGION" --sku Standard_LRS --kind StorageV2 \
  --allow-blob-public-access false --min-tls-version TLS1_2

STORAGE_ID=$(az storage account show -g "$RG" -n "$STORAGE" --query id -o tsv)
ME=$(az ad signed-in-user show --query id -o tsv)
az role assignment create --assignee-object-id "$ME" --assignee-principal-type User \
  --role "Storage Blob Data Contributor" --scope "$STORAGE_ID"

az storage container create --account-name "$STORAGE" --name receipts --auth-mode login
printf '{"hello":"azure"}' > /tmp/cloud-lab-hello.json
az storage blob upload --account-name "$STORAGE" --container-name receipts \
  --name hello.json --file /tmp/cloud-lab-hello.json --auth-mode login

Creating the role assignment requires Microsoft.Authorization/roleAssignments/write—typically Owner, User Access Administrator, or a narrower delegated role. Role propagation is not always instantaneous.

Google Cloud: private Cloud Storage bucket

A bucket belongs to a project and has a chosen location, while its name is globally unique. Prefer uniform bucket-level access so IAM is the single authorisation model, and enable public access prevention for private data.

PROJECT_ID="your-project-id"
REGION="australia-southeast1"
BUCKET="${PROJECT_ID}-cloud-lab"

gcloud config set project "$PROJECT_ID"
gcloud storage buckets create "gs://$BUCKET" --location="$REGION" \
  --uniform-bucket-level-access --public-access-prevention

printf '{"hello":"gcp"}' | gcloud storage cp - "gs://$BUCKET/hello.json"
gcloud storage objects describe "gs://$BUCKET/hello.json"

Databricks: governed files in a volume

A Unity Catalog volume gives non-tabular files a governed three-part namespace. A managed volume lets Unity Catalog manage the underlying object storage lifecycle. An external volume points at a cloud path through a storage credential and external location.

CREATE SCHEMA IF NOT EXISTS workspace.cloud_lab;
CREATE VOLUME IF NOT EXISTS workspace.cloud_lab.inbox;

-- A user needs USE CATALOG, USE SCHEMA, and READ/WRITE VOLUME as appropriate.
GRANT USE CATALOG ON CATALOG workspace TO `cloud-lab-readers`;
GRANT USE SCHEMA ON SCHEMA workspace.cloud_lab TO `cloud-lab-readers`;
GRANT READ VOLUME ON VOLUME workspace.cloud_lab.inbox TO `cloud-lab-readers`;

For external S3, ADLS, or GCS, the chain is: cloud IAM identity/role → Databricks storage credential → external location → external volume/table. Users receive Unity Catalog privileges, not raw cloud credentials.

06 Four toy builds

Build the same idea four ways.

The common workload is Receipt Box: accept a small JSON receipt, run code, persist it, and inspect logs. AWS, Azure, and GCP expose an HTTP service. Databricks implements the platform-appropriate equivalent: ingest a file, transform it into governed Delta tables, query it, and schedule the pipeline.

Before any lab

Use a sandbox account/subscription/project/workspace, set a small budget alert, pick one region, tag/label resources, never paste production data, and run the teardown. Public toy endpoints are for minutes—not unattended weekends.

Lab A · AWS

Lambda Function URL → S3

Infrastructure defined with AWS SAM; CloudWatch Logs is wired by the platform.

30–45 min
HTTPS clientpublic test request
Function URLLambda resource policy
LambdaPython + execution role
S3 /receiptsprivate objects
CloudWatchruntime logs
Human planeYour federated CLI role needs CloudFormation/SAM deployment permissions and permission to pass/create the generated execution role.
Runtime planeLambda assumes its execution role. The inline policy allows only s3:PutObject under the bucket’s receipts/ prefix; basic logging is supplied by SAM.
IngressAuthType: NONE makes this lab URL public. SAM creates the necessary Lambda resource policy. Use IAM, an authorizer/API Gateway, or application auth in real systems.

Files

template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Minimal receipt writer

Resources:
  ReceiptsBucket:
    Type: AWS::S3::Bucket
    Properties:
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        IgnorePublicAcls: true
        BlockPublicPolicy: true
        RestrictPublicBuckets: true

  ReceiptFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: app.lambda_handler
      Runtime: python3.14
      Timeout: 10
      Environment:
        Variables:
          RECEIPTS_BUCKET: !Ref ReceiptsBucket
      Policies:
        - Statement:
            - Effect: Allow
              Action: s3:PutObject
              Resource: !Sub 'arn:${AWS::Partition}:s3:::${ReceiptsBucket}/receipts/*'
      FunctionUrlConfig:
        AuthType: NONE

Outputs:
  ReceiptUrl:
    Value: !GetAtt ReceiptFunctionUrl.FunctionUrl
  ReceiptBucket:
    Value: !Ref ReceiptsBucket
src/app.py
import json, logging, os, uuid
import boto3

log = logging.getLogger()
log.setLevel("INFO")
s3 = boto3.client("s3")
bucket = os.environ["RECEIPTS_BUCKET"]

def lambda_handler(event, context):
    try:
        body = json.loads(event.get("body") or "{}")
        if not {"item", "amount"} <= body.keys():
            return {"statusCode": 400, "body": '{"error":"item and amount required"}'}
        receipt_id = str(uuid.uuid4())
        receipt = {"id": receipt_id, "item": body["item"], "amount": body["amount"]}
        s3.put_object(
            Bucket=bucket,
            Key=f"receipts/{receipt_id}.json",
            Body=json.dumps(receipt).encode(),
            ContentType="application/json",
        )
        log.info("stored receipt %s", receipt_id)
        return {"statusCode": 201, "headers": {"content-type": "application/json"},
                "body": json.dumps(receipt)}
    except (ValueError, TypeError):
        return {"statusCode": 400, "body": '{"error":"invalid JSON"}'}

Build, invoke, inspect, delete

aws sts get-caller-identity
sam build
sam deploy --guided  # choose stack: cloud-receipt-lab; choose your region

URL=$(aws cloudformation describe-stacks --stack-name cloud-receipt-lab \
  --query "Stacks[0].Outputs[?OutputKey=='ReceiptUrl'].OutputValue" --output text)
BUCKET=$(aws cloudformation describe-stacks --stack-name cloud-receipt-lab \
  --query "Stacks[0].Outputs[?OutputKey=='ReceiptBucket'].OutputValue" --output text)

curl -sS -X POST "$URL" -H 'content-type: application/json' \
  -d '{"item":"field-guide","amount":12.50}'
aws s3 ls "s3://$BUCKET/receipts/"
sam logs --stack-name cloud-receipt-lab --tail

# Empty the bucket first; CloudFormation cannot delete a non-empty bucket.
aws s3 rm "s3://$BUCKET" --recursive
sam delete --stack-name cloud-receipt-lab
What SAM created for you

SAM transforms the concise template into CloudFormation resources: an S3 bucket, Lambda function, execution role, log permissions, HTTPS Function URL, and its resource-based invocation permissions. The deployed code receives temporary role credentials automatically; Boto3 discovers them without access keys in the source.

For production, put authentication and throttling in front, validate a schema, add idempotency, alarms and a dead-letter strategy, encrypt with a customer-managed key only when requirements justify its operational cost, and deploy through reviewed CI.

Lab B · Azure

Azure Function → Blob Storage

Flex Consumption function; system-assigned managed identity for application data.

40–60 min
HTTPS clientfunction access key
Function AppPython v2 model
Managed identityOAuth token, no app key
Blob containerprivate receipt blobs
App Insightslogs and requests
Human planeYour Entra identity creates a resource group, storage account, role assignment, and Function App. Role assignment creation requires authority beyond ordinary Contributor.
Runtime planeDefaultAzureCredential uses your Azure CLI identity locally and the Function App’s managed identity in Azure. The same code has no environment-specific secret.
Two storage usesAzure Functions also needs host/deployment storage. This toy lets the platform configure that, while application writes use token-based auth. Advanced production setups can make host storage identity-based too.

Files

function_app.py
import json, logging, os, uuid
import azure.functions as func
from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient, ContentSettings

app = func.FunctionApp()

@app.route(route="receipts", methods=["POST"], auth_level=func.AuthLevel.FUNCTION)
def create_receipt(req: func.HttpRequest) -> func.HttpResponse:
    try:
        body = req.get_json()
        if not {"item", "amount"} <= body.keys():
            return func.HttpResponse('{"error":"item and amount required"}', status_code=400)
        receipt_id = str(uuid.uuid4())
        receipt = {"id": receipt_id, "item": body["item"], "amount": body["amount"]}
        account = os.environ["RECEIPTS_ACCOUNT"]
        service = BlobServiceClient(
            f"https://{account}.blob.core.windows.net",
            credential=DefaultAzureCredential(),
        )
        service.get_blob_client("receipts", f"{receipt_id}.json").upload_blob(
            json.dumps(receipt), overwrite=False,
            content_settings=ContentSettings(content_type="application/json"),
        )
        logging.info("stored receipt %s", receipt_id)
        return func.HttpResponse(json.dumps(receipt), status_code=201,
                                 mimetype="application/json")
    except (ValueError, TypeError):
        return func.HttpResponse('{"error":"invalid JSON"}', status_code=400)
requirements.txt
azure-functions
azure-identity
azure-storage-blob
host.json
{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.0.0, 5.0.0)"
  }
}

Provision, deploy, invoke, delete

RG="cloud-receipt-lab"
REGION="australiaeast"  # confirm with: az functionapp list-flexconsumption-locations
SUFFIX="$RANDOM$RANDOM"
STORAGE="crlab${SUFFIX}"          # lowercase, max 24 chars
APP="cloud-receipt-${SUFFIX}"     # globally unique DNS name

az login
az account show --output table
az group create --name "$RG" --location "$REGION"
az storage account create --name "$STORAGE" --resource-group "$RG" \
  --location "$REGION" --sku Standard_LRS --allow-blob-public-access false

STORAGE_ID=$(az storage account show -g "$RG" -n "$STORAGE" --query id -o tsv)
ME=$(az ad signed-in-user show --query id -o tsv)
az role assignment create --assignee-object-id "$ME" --assignee-principal-type User \
  --role "Storage Blob Data Contributor" --scope "$STORAGE_ID"
az storage container create --account-name "$STORAGE" --name receipts --auth-mode login

az functionapp create --resource-group "$RG" --name "$APP" \
  --storage-account "$STORAGE" --flexconsumption-location "$REGION" \
  --runtime python --runtime-version 3.12 --functions-version 4

APP_PRINCIPAL=$(az functionapp identity assign -g "$RG" -n "$APP" \
  --query principalId -o tsv)
az role assignment create --assignee-object-id "$APP_PRINCIPAL" \
  --assignee-principal-type ServicePrincipal \
  --role "Storage Blob Data Contributor" --scope "$STORAGE_ID"
az functionapp config appsettings set -g "$RG" -n "$APP" \
  --settings RECEIPTS_ACCOUNT="$STORAGE"

func azure functionapp publish "$APP"
URL=$(func azure functionapp list-functions "$APP" --show-keys \
  | grep -Eo 'https://[^ ]+' | head -1)
curl -sS -X POST "$URL" -H 'content-type: application/json' \
  -d '{"item":"field-guide","amount":12.50}'
az storage blob list --account-name "$STORAGE" --container-name receipts \
  --auth-mode login --output table

az group delete --name "$RG"  # removes every resource in this lab group
If the first write returns 403

First confirm the Function App has a system-assigned identity and the role is assigned to that principal—not your own user. Then confirm the role is a Blob data role, the environment variable contains the right account name, and the container exists. Newly created role assignments can take time to propagate. Use Application Insights/Function logs for the precise error before broadening permissions.

Lab C · Google Cloud

Cloud Run → Cloud Storage

A tiny Flask container built from source; dedicated service account with create-only object access.

30–45 min
HTTPS clientpublic Cloud Run URL
Cloud Runautoscaled container
Service accountApplication Default Credentials
Cloud Storageprivate objects
Cloud Loggingstdout + request logs
Human planeThe deployer needs source-deployment permissions, permission to act as the runtime service account, and authority to enable APIs or an admin must do those setup actions.
Build planegcloud run deploy --source uses buildpacks/Cloud Build and stores the built image in Artifact Registry. This is an extra resource and cost/lifecycle surface.
Runtime planeThe Cloud Run revision runs as receipt-writer. Bucket-level roles/storage.objectCreator permits new objects but not reads, lists, overwrites, or deletes.

Files

main.py
import json, logging, os, uuid
from flask import Flask, jsonify, request
from google.cloud import storage

app = Flask(__name__)
client = storage.Client()

@app.post("/")
def create_receipt():
    body = request.get_json(silent=True) or {}
    if not {"item", "amount"} <= body.keys():
        return jsonify(error="item and amount required"), 400
    receipt_id = str(uuid.uuid4())
    receipt = {"id": receipt_id, "item": body["item"], "amount": body["amount"]}
    blob = client.bucket(os.environ["RECEIPTS_BUCKET"]).blob(
        f"receipts/{receipt_id}.json"
    )
    blob.upload_from_string(json.dumps(receipt), content_type="application/json")
    logging.info("stored receipt %s", receipt_id)
    return jsonify(receipt), 201

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=int(os.environ.get("PORT", "8080")))
requirements.txt
Flask
gunicorn
google-cloud-storage
Procfile
web: gunicorn --bind :$PORT main:app

Provision, deploy, invoke, delete

PROJECT_ID="your-project-id"
REGION="australia-southeast1"
BUCKET="${PROJECT_ID}-receipt-lab"
SERVICE_ACCOUNT="receipt-writer@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud auth login
gcloud config set project "$PROJECT_ID"
gcloud services enable run.googleapis.com cloudbuild.googleapis.com \
  artifactregistry.googleapis.com

gcloud storage buckets create "gs://$BUCKET" --location="$REGION" \
  --uniform-bucket-level-access --public-access-prevention
gcloud iam service-accounts create receipt-writer \
  --display-name="Receipt Box runtime"
gcloud storage buckets add-iam-policy-binding "gs://$BUCKET" \
  --member="serviceAccount:${SERVICE_ACCOUNT}" \
  --role="roles/storage.objectCreator"

gcloud run deploy receipt-box --source . --region "$REGION" \
  --service-account "$SERVICE_ACCOUNT" \
  --set-env-vars "RECEIPTS_BUCKET=$BUCKET" --allow-unauthenticated

URL=$(gcloud run services describe receipt-box --region "$REGION" \
  --format='value(status.url)')
curl -sS -X POST "$URL" -H 'content-type: application/json' \
  -d '{"item":"field-guide","amount":12.50}'
gcloud storage ls "gs://$BUCKET/receipts/"
gcloud run services logs read receipt-box --region "$REGION" --limit 20

gcloud run services delete receipt-box --region "$REGION"
gcloud storage rm --recursive "gs://$BUCKET"
gcloud iam service-accounts delete "$SERVICE_ACCOUNT"
# Also inspect/delete the cloud-run-source-deploy Artifact Registry repository.
Why Cloud Run is a useful first GCP service

It makes the container contract visible—listen on PORT, remain stateless, write durable state elsewhere—while hiding nodes and clusters. Source deployment also reveals the separation between deployer, build identity, runtime identity, image registry, and serving service. Those identities need different permissions in a serious environment.

Lab D · Databricks

Volume → Delta tables → SQL → Job

A governed mini data pipeline on serverless compute—the platform’s natural “full service” shape.

25–40 min
JSONL fileUnity Catalog volume
Notebookserverless Spark compute
Bronze Deltatyped receipt rows
Daily tablebusiness aggregate
SQL / Jobquery + scheduled run
Why differentDatabricks is not normally the public HTTP edge for a generic microservice. Its core path is governed data + elastic compute + workflows + analytics/AI. Databricks Apps and Lakebase can host data-centric applications when that is the requirement.
Human planeYour account identity must be assigned to the workspace and allowed to use compute. Unity Catalog separately authorises catalog, schema, volume, and tables.
Runtime planeA notebook attaches to serverless compute. A Lakeflow Job later runs the notebook under its configured run identity; that identity needs the same data privileges.

The lab uses the workspace catalog named workspace, which is present in Free Edition and many newer workspaces. Run SELECT current_catalog() or SHOW CATALOGS first; replace workspace with your assigned sandbox catalog if your administrator uses another layout.

Notebook cell 1 · create governed storage

%sql
CREATE SCHEMA IF NOT EXISTS workspace.cloud_lab;
CREATE VOLUME IF NOT EXISTS workspace.cloud_lab.inbox;

Notebook cell 2 · write a tiny source file

%python
import json

receipts = [
    {"id":"r-001", "item":"field-guide", "amount":12.50,
     "created_at":"2026-08-03T09:00:00Z"},
    {"id":"r-002", "item":"notebook", "amount":7.25,
     "created_at":"2026-08-03T10:30:00Z"},
]
path = "/Volumes/workspace/cloud_lab/inbox/receipts.jsonl"
dbutils.fs.put(path, "\n".join(json.dumps(r) for r in receipts), True)
print(path)

Notebook cell 3 · ingest and transform

%sql
CREATE OR REPLACE TABLE workspace.cloud_lab.receipts_bronze
USING DELTA AS
SELECT
  CAST(id AS STRING) AS id,
  CAST(item AS STRING) AS item,
  CAST(amount AS DECIMAL(10,2)) AS amount,
  CAST(created_at AS TIMESTAMP) AS created_at
FROM json.`/Volumes/workspace/cloud_lab/inbox/receipts.jsonl`;

CREATE OR REPLACE TABLE workspace.cloud_lab.receipts_daily
USING DELTA AS
SELECT date(created_at) AS receipt_date,
       count(*) AS receipt_count,
       sum(amount) AS revenue
FROM workspace.cloud_lab.receipts_bronze
GROUP BY date(created_at);

SELECT * FROM workspace.cloud_lab.receipts_daily;

Turn it into a running service

  1. Attach the notebook to Serverless compute and run all cells. Inspect both tables in Catalog Explorer.
  2. Open Jobs & Pipelines → Create → Job; select this notebook as the first task and serverless compute.
  3. Choose a run identity with access to the catalog/schema/volume, click Run now, and inspect task output and duration.
  4. Open the SQL editor/warehouse, query workspace.cloud_lab.receipts_daily, and optionally make a small dashboard tile.
  5. For a team, grant a group parent USE privileges plus SELECT on only the published table; do not grant raw volume write unless needed.
GRANT USE CATALOG ON CATALOG workspace TO `cloud-lab-readers`;
GRANT USE SCHEMA ON SCHEMA workspace.cloud_lab TO `cloud-lab-readers`;
GRANT SELECT ON TABLE workspace.cloud_lab.receipts_daily TO `cloud-lab-readers`;

-- Teardown: this removes managed tables, the volume, and its managed files.
DROP SCHEMA workspace.cloud_lab CASCADE;
External storage, one level deeper

For an existing S3/ADLS/GCS path, an admin creates or references a cloud identity, wraps it in a Unity Catalog storage credential, binds that credential to a URL as an external location, then permits a data owner to create an external volume/table. Consumers receive privileges on the resulting Unity Catalog object. This separates cloud secrets and infrastructure ownership from everyday data permissions.

Use a Declarative Automation Bundle when this notebook, job, permissions, and target environments should live in source control and move through CI/CD.

07 From toy to production

A working endpoint is the beginning, not the finish.

The labs prove resource creation, runtime identity, data access, invocation, observability, and teardown. A production service adds explicit engineering around every failure mode the toy ignores.

Identity
  • Federated human sign-in and MFA
  • Separate deployer, runtime, and break-glass identities
  • Least-privilege resource/prefix roles
  • Automated credential rotation or no stored credential
Network
  • Document public and private endpoints
  • Restrict ingress; controlled egress and DNS
  • TLS and certificate lifecycle
  • Multi-zone placement where the service requires it
Application
  • Schema validation, size limits, authentication
  • Idempotency, timeouts, retries with backoff
  • Queue for slow/unreliable downstream work
  • Versioned API and safe database migrations
Reliability
  • SLOs and user-visible health checks
  • Backups with tested restore
  • Alarms tied to an owned response
  • Capacity, quota, and regional failure plan
Delivery
  • Infrastructure and app code in version control
  • Repeatable dev/stage/prod environments
  • Tests, policy checks, review, progressive rollout
  • Artifact provenance and dependency scanning
Operations & cost
  • Structured logs, metrics, traces, audit trail
  • Tags/labels for owner, service, environment, cost centre
  • Budgets, anomaly alerts, retention/lifecycle rules
  • Runbooks and deletion/retention ownership

The architecture progression

Level 0 · manualConsole/CLI exploration. Useful for learning, hard to reproduce, easy to forget.
Level 1 · declarativeSAM/CloudFormation, Bicep/azd, Terraform, or Databricks Bundles describes the whole environment and teardown.
Level 2 · deliveryCI validates, plans, tests, scans, deploys to a non-production environment, then promotes with approval.
Level 3 · platformA paved path creates accounts/projects/subscriptions, networking, identity, observability, policies, and templates for many teams.
A production heuristic

Prefer the most managed service that meets your constraints. Move down toward Kubernetes or VMs only when a requirement—not familiarity—pays for the extra operating surface.

08 What else matters

The market is bigger than four brand names.

The latest available Stack Overflow survey still treats cloud development as a broad tool category, while CNCF’s 2025 survey reports Kubernetes in production at 82% among container-using respondents. The practical implication: learn one base cloud deeply, but keep portable concepts—containers, Kubernetes, Terraform, SQL, identity federation, and observability—in your core toolkit.

Kubernetes

The portable control plane

Not a cloud vendor. It standardises container scheduling and an extension API across EKS, AKS, GKE, on-prem, and others. High demand, but a poor first answer when serverless/PaaS meets the need.

Snowflake

Cloud data platform

High-value for analytics roles. Separates central data storage, independent virtual warehouses, and cloud services. Like Databricks, it complements rather than replaces the base cloud.

Microsoft Fabric

SaaS analytics estate

Important in Microsoft-heavy data/BI organisations. It packages ingestion, lake, warehouse, real-time analytics, data science, and Power BI more as SaaS than raw Azure primitives.

Cloudflare

Edge developer platform

Workers, R2, D1, KV, Queues, and Durable Objects form a compact globally distributed application stack. Particularly relevant for web performance, edge compute, security, and low-ops apps.

Oracle Cloud (OCI)

Enterprise and Oracle estates

Worth targeted learning for Oracle Database, ERP, telecom, regulated, and existing Oracle-heavy environments. The same IAM/network/compute/storage concepts transfer.

Developer PaaS

Vercel, Render, Fly.io, Heroku

Excellent for product delivery with smaller infrastructure teams. They reduce knobs rather than invalidate cloud fundamentals; many eventually connect to AWS/Azure/GCP data and identity.

“In demand” depends on role and geography: platform engineers see Kubernetes/Terraform; enterprise developers see Azure; data engineers see Databricks/Snowflake/Fabric; product teams may see Cloudflare or developer PaaS. Validate against actual job descriptions in your target market.

09 A practical learning path

Six weeks from vocabulary to evidence.

The goal is not console fluency. It is the ability to explain, deploy, debug, secure, observe, cost, and delete one small workload—and then translate it.

Week 1 · Azure depthMap tenant/subscription/resource group. Run the Blob and Function lab. Rebuild in Bicep or azd. Deliberately remove the data role, diagnose 403, restore it.
Week 2 · AWS translationLearn account/region/VPC/role/ARN. Run the SAM lab. Inspect the generated role, resource policy, CloudFormation stack, logs, and bill.
Week 3 · GCP translationLearn organization/project/global VPC/service account/API enablement. Run Cloud Run. Compare the deployer, builder, and runtime identities.
Week 4 · data planeRun the Databricks pipeline. Explain managed vs external data, volume vs table, workspace vs catalog permission, and OLTP vs lakehouse.
Week 5 · production passAdd authentication, schema tests, structured logs, an alert, a budget, tags, CI, and a repeatable teardown to one chosen implementation.
Week 6 · portfolio evidenceDraw the topology, threat model it, document one failure, show cost assumptions, and demo a clean deploy → request → log → data → destroy loop.

Questions you should be able to answer without a console

  • What is the administrative, billing, region, network, and data scope of this resource?
  • Which identity deploys it, which identity runs it, and which identity reads its output?
  • Which exact action is allowed on which exact resource path—and what higher-level guardrail can still deny it?
  • Is the endpoint public, private, or service-internal? How does DNS resolve from the workload?
  • Where do logs, metrics, traces, audit events, build artifacts, and cost allocation data go?
  • What persists after compute stops? What happens if a zone or region fails?
  • What command or pull request recreates it? What command safely deletes it?
10 Compact glossary

The words behind the products.

Principal

A human, group, workload, or federated identity that can authenticate and receive permissions.

Role / policy

A named permission set or policy document describing actions, resources, effects, and conditions. Exact semantics vary.

ARN / resource ID / full name

The provider-specific globally meaningful identifier used to target a resource in APIs and policies.

Tenant / account / subscription / project

Administrative containers with different identity, billing, quota, and isolation responsibilities. Never assume they are exact synonyms.

Region / zone

A geographic deployment area and an isolated failure domain inside it. Service-level scope may be global, regional, or zonal.

VPC / VNet

A software-defined private network. AWS and Azure networks are regional; GCP VPC networks are global.

Security group / NSG / firewall rule

Stateful or policy-based network filters controlling allowed traffic. Attachment and evaluation models differ.

Private endpoint

A private-network interface/address for reaching a managed service without using its public route.

Serverless

An operating model where the provider manages fleet capacity and scaling. Servers still exist; you manage fewer of their lifecycle details.

Object key

The string name of an object inside a bucket/container. Prefixes often look like folders but are not always filesystem directories.

IaC

Infrastructure as code: declarative, reviewable resource definitions applied by an engine that calculates changes.

Egress

Data leaving a service, zone, region, or provider boundary. It can affect both architecture and cost.

Shared responsibility

The provider secures the underlying cloud; you remain responsible for configurations, identities, data, application logic, and choices that vary by service model.

Lakehouse

An architecture combining low-cost object storage and open/table formats with warehouse-style management, SQL performance, governance, and ML access.

11 Primary sources

Research trail.

Reviewed against current official documentation on 3 August 2026. Cloud documentation changes continuously; follow the linked setup page before deploying, especially for runtimes, free offers, region availability, and preview features.

Scope notes

  • Mappings are architectural analogies, not feature parity claims.
  • Commands are educational and assume appropriate sandbox permissions.
  • Exact prices and free-tier quotas are intentionally not frozen into the guide.
  • Region names in labs favour an Australian reader; choose your compliant supported region.