Cloud Landing Zone Design: Enterprise Blueprint

Design a secure, scalable cloud foundation. Covers account/subscription structure, networking, identity, guardrails, logging, and the landing zone pattern for AWS and Azure.

A Cloud Landing Zone (CLZ) is a pre-configured, repeatable foundation for deploying cloud workloads at scale. It defines the core infrastructure, security, governance, and operational standards that every team in an enterprise can use to launch and manage cloud applications. It matters when an organisation transitions from ad-hoc cloud deployments to a structured, governed, and scalable cloud practice—typically after initial experimentation, when teams begin to deliver cloud-native services in parallel across multiple domains.

Foundational Configuration: The Core CLZ Blueprint

The CLZ begins with a declarative configuration that defines the baseline environment across one or more cloud providers. This configuration is stored in version-controlled repositories, typically using Git, and applied via infrastructure-as-code (IaC) tools such as Terraform, Pulumi, or AWS CloudFormation.

A CLZ configuration consists of a set of modules, each responsible for a distinct domain: networking, identity, security, observability, and operations. These modules are applied in a specific order to ensure consistency and idempotency.

Networking and Connectivity

The foundation of any CLZ is a network topology that enables secure, scalable, and performant connectivity between services.

A typical CLZ defines:


module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.14.0"

  name                 = "prod-core"
  cidr                 = "10.0.0.0/16"
  azs                  = ["us-west-2a", "us-west-2b", "us-west-2c"]
  private_subnets      = ["10.0.10.0/24", "10.0.20.0/24", "10.0.30.0/24"]
  public_subnets       = ["10.0.100.0/24", "10.0.110.0/24", "10.0.120.0/24"]
  enable_nat_gateway   = true
  single_nat_gateway   = true
  enable_dns_hostnames = true
  enable_dns_support   = true
}

Subnet delegation to route tables is critical. A common failure mode is forgetting to assign the correct route table to a subnet, resulting in instances in private subnets being unreachable from the internet or from other services. Another silent failure occurs when a new subnet is added to the VPC but is not associated with the correct route table, causing traffic to default to the main route table and bypassing custom routing rules.

Identity and Access Management (IAM)

Central to the CLZ is a unified identity model based on roles, policies, and federated authentication.

The CLZ defines:

Example policy for a data-engineer role:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket"
      ],
      "Resource": "arn:aws:s3:::data-lake/*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "glue:GetDatabase",
        "glue:GetTable",
        "glue:CreateDatabase",
        "glue:CreateTable"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "athena:StartQueryExecution",
        "athena:GetQueryExecution"
      ],
      "Resource": "*"
    }
  ]
}

Roles are assumed via AWS Security Token Service (STS) or a similar identity provider, with session tokens that include:

A common failure mode is incorrect Principal configuration in the role trust policy, leading to failure when a service tries to assume a role. For instance, if a Lambda function in 123456789012 tries to assume a role in 210987654321, but the Principal in the role is set to 123456789012 instead of 210987654321, the assumption fails silently with:

{
  "error": "AccessDenied",
  "message": "User: arn:aws:iam::123456789012:role/LambdaExecution is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::210987654321:role/ProdDataEngineer"
}

Security and Compliance

Security in the CLZ is enforced through a combination of policies, tools, and automated checks.

The CLZ defines:

// Example SCP: enforce encryption and tagging
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateVolume",
        "ec2:CreateSnapshot"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "ec2:Encrypted": "true"
        }
      }
    },
    {
      "Effect": "Deny",
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl"
      ],
      "Resource": "arn:aws:s3:::data-lake/*",
      "Condition": {
        "Null": {
          "s3:x-amz-meta-project": true
        }
      }
    }
  ]
}

Security is reinforced by automated scanning tools such as Checkov, Terratest, or custom pipelines that run before every deployment.

The CLZ includes a standard CI/CD pipeline that:

Observability and Operations

A CLZ includes a unified observability stack that enables visibility across all services.

The core observability components are:

A standard otel-collector-config.yaml is included in the CLZ:

receivers:
  otlp:
    protocols:
      grpc:
      http:
exporters:
  prometheus:
    endpoint: "0.0.0.0:8888"
    namespace: "cloud_landing_zone"
  logging:
    loglevel: "info"
  awscloudwatch:
    region: "us-west-2"
    endpoint: "https://monitoring.us-west-2.amazonaws.com"
    metric_version: "2010-08-01"
    default_dimensions:
      Environment: "prod"
      Service: "cloud-lz"
processors:
  batch:
    send_batch_max_size: 1000
    timeout: 10s
  memory_limiter:
    limit_mib: 100
  resource:
    attributes:
      service.name: "cloud-lz"
      service.version: "1.0"
      deployment.environment: "prod"
extensions:
  health_check:
  pprof:
    endpoint: "0.0.0.0:8889"
  zpages:
    endpoint: "0.0.0.0:8890"
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch, memory_limiter, resource]
      exporters: [awscloudwatch]
    metrics:
      receivers: [otlp]
      processors: [batch, memory_limiter, resource]
      exporters: [prometheus]
    logs:
      receivers: [otlp]
      processors: [batch, memory_limiter, resource]
      exporters: [logging]

This configuration is deployed via Helm charts or container manifests. A common failure is missing the service.name attribute in the resource processor, resulting in metrics and traces being grouped under a generic unknown service in the monitoring dashboard.

Operational Standards and Patterns

The CLZ defines a set of operational patterns that guide how teams build and run services.

Each service must:

  {
    "status": "healthy",
    "timestamp": "2023-07-12T10:00:00Z",
    "details": {
      "database": "healthy",
      "cache": "healthy",
      "dependencies": {
        "auth-service": "reachable",
        "storage": "reachable"
      }
    }
  }

A failure mode is confusing /health and /ready endpoints. A service may report healthy but not be ready to serve requests because it hasn’t loaded its cache or connected to all downstream services. This leads to rolling deployments that fail silently: instances become healthy but still return 500 errors until the cache warms up.

The CLZ also defines a standard Makefile for local development:

.PHONY: build test deploy

build:
	docker build -t myapp:latest .

test:
	docker run --rm myapp:latest pytest tests/

deploy:
	kubectl apply -f k8s/
	kubectl rollout status deployment/myapp

dev:
	docker-compose up --build

This ensures that every team uses the same workflow. A common mistake is forgetting to run make deploy after make build, leading to new images being built but not deployed.

Evolving the Landing Zone

The CLZ is not static. It evolves through a versioning and change management process.

Each CLZ configuration is versioned using semantic versioning (e.g., v1.2.3). Changes are proposed via pull requests, reviewed, tested in a staging environment, and promoted to production.

A key mechanism is the CLZ version manifest, stored as clz-version.yaml:

version: "1.2.3"
components:
  - name: "networking"
    version: "3.14.0"
    source: "git::https://github.com/enterprise/infrastructure-modules.git//networking"
  - name: "iam"
    version: "2.0.1"
    source: "git::https://github.com/enterprise/iam-policies.git//roles"
  - name: "observability"
    version: "1.5.0"
    source: "helm::https://charts.example.com/observability"

When a new CLZ version is released, teams can update their environment by:

A silent failure occurs when a new version of a component introduces breaking changes but the clz-version.yaml file is not updated, or when the terraform version -upgrade command is omitted. This leads to version drift across environments and inconsistent configurations.

The CLZ is complete when every new team can launch a service using the same core configuration, with minimal onboarding. It is successful when a new service can be deployed end-to-end—code to production—with a single command, and all required policies, network rules, monitoring, and access controls applied automatically.

This page was rewritten on 17 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.