AWS Diagrams

Last updated:

IAM Policy Evaluation in One Account

Flow

The order AWS checks each policy type, and where a request exits.

How AWS evaluates IAM policies for a request within one account An authenticated request passes a series of checks in order. An explicit Deny in any applicable policy ends in Deny. Resource control policies and service control policies must each allow the action, or the request is denied. If a resource-based policy allows the action for the requesting IAM user or role session by name, the request is allowed with no further checks. If it names the role ARN instead, the identity-based check is skipped but the permissions boundary and session policy still apply. Otherwise the identity-based policies must allow the action, and any permissions boundary and session policy must allow it too. Passing every check ends in Allow. Authenticated request Explicit Deny in any policy? every applicable policy type Do the RCPs allow it? resource's account, in an organization Do the SCPs allow it? principal's account, in an organization Resource-based policy allows it? and whom does it name? Identity-based policy allows it? user, group, or role policies Permissions boundary allows it? only if a boundary is set Session policy allows it? only if one was passed Allow Deny no yes no no no no no names the user or session names the role ARN Within one account. A cross-account request is evaluated in both accounts, and both must allow it.

Cross-Account Access Through a Role

Trust boundary

Which policy in which account allows each step of a role assumption.

Cross-account access through an IAM role A principal in the trusted account A, here a deployment pipeline running as a role session, has an identity-based policy allowing sts:AssumeRole on a role in the trusting account B. The role's trust policy in account B names account A as a principal that may assume it. AWS STS returns temporary credentials for a role session. The role session then calls resources in account B, and the role's permissions policy decides what those calls may do. Tools account A (trusted) Production account B (trusting) Deployment pipeline [Principal: role session in A] identity policy allows sts:AssumeRole on the role in B ProdDeploy [IAM role] trust policy: account A may assume permissions policy: deploy actions Resources in B S3 buckets, RDS, EC2 1. AssumeRole 2. temporary credentials 3. calls as role session Step 1 needs an allow on both sides: the identity policy in A and the trust policy in B. Step 3 is evaluated in account B, mainly against the role's permissions policy.

Workforce Sign-In Through IAM Identity Center

Flow

How identities, permission sets, and per-account roles combine at sign-in.

Workforce sign-in through IAM Identity Center An external identity provider such as Okta, Microsoft Entra ID, or Google Workspace syncs users and groups into IAM Identity Center with SCIM. In Identity Center, permission sets are assigned to users and groups for specific accounts, and Identity Center provisions a matching AWSReservedSSO role in each assigned member account. A person opens the AWS access portal or the CLI, signs in through the identity provider with SAML, picks an account and permission set, and receives temporary credentials for a session of that account's AWSReservedSSO role. Identity provider [external: Okta, Entra ID, Google Workspace] IAM Identity Center [organization instance] users and groups permission sets account assignments Member account: prod AWSReservedSSO_... [IAM role] Member account: dev AWSReservedSSO_... [IAM role] Person [workforce user] AWS access portal or CLI [aws sso login] SCIM sync provisions a role per assignment 1. opens 2. SAML sign-in 3. picks an account and permission set, gets a session Dashed lines are configuration set up in advance. Solid lines are one person signing in.

SCP Inheritance From Root to Account

Rules

An action must be allowed at every level above an account.

How service control policies are inherited from the organization root to an account The organization root, the Workloads OU, and the App1 production account each have the FullAWSAccess SCP attached. The Production OU instead has an allow-list SCP that allows only EC2, S3, and RDS actions. For ec2:RunInstances, every level allows the action, so the SCPs permit it and IAM policies then decide. For dynamodb:PutItem, the Production OU's allow list doesn't include DynamoDB, so the action is denied for every account under that OU, even though the account itself has FullAWSAccess attached. Hierarchy and attached SCPs ec2:RunInstances dynamodb:PutItem Organization root FullAWSAccess Workloads OU FullAWSAccess Production OU allow list: ec2, s3, rds only App1 production account FullAWSAccess allowed allowed allowed allowed allowed allowed not allowed allowed SCPs permit it IAM policies decide next Denied for every account in the OU Each level's SCPs must allow the action. An allow at the account can't restore what a level above it left out.

Where SCPs and RCPs Apply

Trust boundary

SCPs check the caller's account; RCPs check the resource's account.

Where service control policies and resource control policies apply Two member accounts sit inside an organization. A role in account A calls an S3 bucket in account B. That request is checked twice: against the SCPs of account A, where the caller lives, and against the RCPs of account B, where the resource lives. A principal in an account outside the organization calls the same bucket. SCPs don't apply to it, because it isn't in the organization, so only the RCPs of account B can stop it. Your organization Member account A App role [caller] Member account B S3 bucket [resource] Account outside the org External principal [caller] SCPs of A RCPs of B RCPs of B none of your SCPs apply Each dot is a check that must allow the request, on top of the IAM and bucket policies.

Subnets, Route Tables, and the Path Out

C4 · Deployment

A two-AZ VPC whose route tables make each subnet public, private, or isolated.

A two-Availability-Zone VPC with public, private, and isolated subnets and the route tables that define them A VPC with CIDR 10.0.0.0/16 spans two Availability Zones. Each zone has a public subnet holding a load balancer node and a NAT gateway, a private app subnet, and an isolated data subnet. An internet gateway is attached to the VPC. The public route table sends 0.0.0.0/0 to the internet gateway. Each app subnet's route table sends 0.0.0.0/0 to the NAT gateway in its own zone, and the NAT gateway reaches the internet through the internet gateway. The data route table has only the local route, so data subnets have no path out of the VPC. Internet VPC 10.0.0.0/16 Internet gateway Availability Zone a Availability Zone b Public subnet 10.0.1.0/24 load balancer node NAT gateway Public subnet 10.0.2.0/24 load balancer node NAT gateway Private subnet (app) 10.0.11.0/24 instances, containers Private subnet (app) 10.0.12.0/24 instances, containers Isolated subnet (data) 10.0.21.0/24 no path out of the VPC Isolated subnet (data) 10.0.22.0/24 no path out of the VPC Route tables Public (both public subnets) 10.0.0.0/16 local 0.0.0.0/0 igw App, zone a 10.0.0.0/16 local 0.0.0.0/0 nat (zone a) App, zone b 10.0.0.0/16 local 0.0.0.0/0 nat (zone b) Data (both data subnets) 10.0.0.0/16 local Arrows show outbound internet traffic from each app subnet, through the NAT gateway in its own zone.

Where Network ACLs and Security Groups Check Traffic

Trust boundary

One request and its response, checked at the subnet edge and the network interface.

Where network ACLs and security groups check a request and its response A client on the internet sends a request from ephemeral port 50123 to port 443 on an instance in a public subnet. The request passes the internet gateway, then the network ACL at the subnet edge, which must have an inbound rule allowing port 443, then the security group at the instance's network interface, which must have an inbound rule allowing port 443. The response travels back the other way. The security group lets it out without checking a rule, because it tracks the connection. The network ACL checks it against its outbound rules, which must allow destination port 50123, because the network ACL keeps no connection state. Client [internet] Internet gateway Public subnet (network ACL at its edge) Security group Instance [listens on 443] 1 2 request: port 50123 to 443 3 4 response: 443 to port 50123 Checked against rules Passed without a rule check 1 Network ACL inbound: a rule must allow TCP 443. 2 Security group inbound: a rule must allow TCP 443. 3 Security group: tracked connection, response allowed. 4 Network ACL outbound: a rule must allow port 50123.

Load Balancer Nodes and Target Groups in Two Tiers

C4 · Deployment

An internet-facing and an internal load balancer, with nodes and targets per AZ.

An internet-facing load balancer and an internal load balancer, each with a node in two Availability Zones Clients resolve the internet-facing load balancer's DNS name and receive the IP addresses of its two nodes, one in a public subnet in each of two Availability Zones. Each node's listener applies its rules and forwards to the web target group, whose instances sit in private subnets in both zones. The web instances call an internal load balancer, whose nodes have private addresses in each zone, and it forwards to the service target group in private subnets in both zones. Clients DNS name resolves to both nodes VPC Availability Zone a Availability Zone b Internet-facing load balancer Node Node Web target group Web instance Web instance Internal load balancer Node Node Service target group Service instance Service instance Public subnets public node addresses; listener rules choose the target group Private subnets reached by private IP Private subnets private node addresses Private subnets reached by private IP

Cross-Zone Load Balancing On and Off

Rules

How 2 and 8 targets in two zones split traffic with cross-zone on and off.

How cross-zone load balancing changes each target's share of traffic Two Availability Zones each hold one load balancer node, and each node receives 50 percent of client traffic. Zone a has 2 targets and zone b has 8. With cross-zone load balancing on, each node spreads its traffic across all 10 targets, so every target receives 10 percent. With it off, each node sends traffic only to targets in its own zone, so the 2 targets in zone a receive 25 percent each and the 8 targets in zone b receive 6.25 percent each. Cross-zone on (ALB default) Availability Zone a Load balancer node receives 50% 10% 10% Availability Zone b Load balancer node receives 50% 10% 10% 10% 10% 10% 10% 10% 10% Cross-zone off (NLB and GWLB default) Availability Zone a Load balancer node receives 50% 25% 25% Availability Zone b Load balancer node receives 50% 6.25% 6.25% 6.25% 6.25% 6.25% 6.25% 6.25% 6.25% Each box is one target and its share of all client traffic. Dashed arrows are traffic crossing between zones.

Ingress Inspection Through a Gateway Load Balancer

C4 · Dynamic

An inbound request detoured through firewall appliances by route tables.

How route tables send inbound traffic through a Gateway Load Balancer and its appliances A request from the internet enters the application VPC through the internet gateway. An edge route table on the internet gateway sends traffic for the application subnet to a Gateway Load Balancer endpoint in its own subnet. The endpoint forwards the traffic privately to the Gateway Load Balancer in a separate inspection VPC. The Gateway Load Balancer wraps each packet in GENEVE on UDP port 6081 and sends it to a firewall appliance, which inspects it and returns it. The Gateway Load Balancer hands the packet back to the endpoint, which delivers it to the application instances with its original addresses. The application subnet's default route points at the endpoint, so responses take the same path back, and the endpoint subnet's default route sends them out through the internet gateway. Internet Application VPC Internet gateway edge route table: app subnet → endpoint Endpoint subnet route table: 0.0.0.0/0 → IGW Gateway Load Balancer endpoint Application subnet Application instances route table: 0.0.0.0/0 → endpoint Inspection VPC Gateway Load Balancer Firewall appliances [Auto Scaling group] GENEVE, UDP 6081 1 2 3 4 5 6 7 Responses leave the app subnet by its default route and retrace the same path through the same appliance.

Nested Routing Policies With Health Checks

Dependency graph

Latency records over failover and weighted sets, with one failing endpoint dropped.

A latency routing tree whose branches are a failover set and a weighted set The name app.example.com has two latency records, one for us-east-1 and one for eu-west-1. The us-east-1 record is an alias to a failover set whose primary is an application load balancer and whose secondary is a standby load balancer. The eu-west-1 record is an alias to a weighted set sending 90 percent to a blue load balancer and 10 percent to a green one. Evaluate target health is on for the aliases. The us-east-1 primary's health check is failing, so the failover set answers with the secondary, and the us-east-1 latency record stays in service. app.example.com [latency records] us-east-1 record [alias to a failover set] eu-west-1 record [alias to a weighted set] Primary ALB health check failing Standby ALB [secondary] Blue ALB [weight 90] Green ALB [weight 10] Evaluate target health is on at each alias. The failing primary drops out, so the failover set answers with the standby, and the us-east-1 latency record stays in service. If both of its load balancers failed, that record would drop out too, and every user would get eu-west-1.

Hybrid DNS With Resolver Endpoints

C4 · Dynamic

Inbound and outbound endpoints resolving names across a VPC and a data center.

How inbound and outbound Resolver endpoints connect DNS between a VPC and an on-premises network An on-premises network and a VPC are connected by a VPN or Direct Connect. For an on-premises client resolving an AWS name, the corporate DNS server forwards the query to an inbound endpoint in the VPC, which hands it to the VPC Resolver, and the VPC Resolver answers from a private hosted zone. For an EC2 instance resolving an on-premises name, the VPC Resolver matches a forwarding rule for the on-premises domain and sends the query out through an outbound endpoint to the corporate DNS server. On-premises network Corporate DNS owns corp.example.com VPN or Direct Connect VPC Inbound endpoint [ENIs in two AZs] Outbound endpoint [ENIs in two AZs] forwarding rule: corp.example.com Private hosted zone aws.example.com VPC Resolver [VPC base + 2] EC2 instance asks for db.corp.example.com On-premises clients resolving AWS names VPC resources resolving on-premises names

CloudFront Cache Tiers on a Miss

Flow

Edge locations, regional edge caches, and Origin Shield collapsing misses toward one origin.

How CloudFront's cache tiers funnel cache misses toward the origin Viewers in three places each reach their nearest edge location. On a miss, two of the edge locations ask the same regional edge cache and the third asks another. On a miss there, both regional edge caches ask Origin Shield, an optional cache layer in one Region near the origin, so as few as one request per object reaches the origin. CloudFront Functions run at the edge locations, and Lambda@Edge functions run at the regional edge caches, with origin triggers moving to the Origin Shield Region when it is on. Writes and dynamic requests skip the cache tiers and go from the edge location straight to the origin. Viewers Edge locations Regional edge caches Origin Shield Origin Viewer Viewer Viewer Edge location Edge location Edge location Regional cache Regional cache Origin Shield [optional, one Region] Origin [S3, ALB, API] CloudFront Functions run here Lambda@Edge runs here As few as one request per object Lambda@Edge origin triggers run here when on Arrows show a cacheable request missing and moving inward. Each tier answers from its own cache when it can, and only a miss goes further. Writes such as POST and PUT, and requests CloudFront treats as dynamic, go from the edge location straight to the origin.

API Gateway Endpoint Types and VPC Links

C4 · Deployment

Three ways clients reach a REST API, and the VPC link out to private backends.

How clients reach edge-optimized, Regional, and private REST API endpoints, and how a VPC link reaches private backends An edge-optimized endpoint is reached through a CloudFront distribution that API Gateway manages. A Regional endpoint is reached directly, optionally through a CloudFront distribution you own. A private endpoint is reached only from inside a VPC, through an interface VPC endpoint. On the other side, the API reaches a Network or Application Load Balancer in private subnets through a VPC link. Edge-optimized Client CloudFront [managed by API Gateway] Regional Client Your CloudFront [optional] Private: from a VPC only Client in VPC Interface VPC endpoint API Gateway [REST API, one Region] VPC link NLB or ALB [private subnets] Outbound Edge-optimized and Regional endpoints are reached over the internet, and a private endpoint only through an interface endpoint. A VPC link runs the other way, from the API out to backends with no public address.
Trust boundary

A consumer reaches one provider service through an endpoint, one direction only.

A consumer VPC reaching a provider's service through an interface endpoint and AWS PrivateLink A consumer VPC and a provider VPC both use the CIDR 10.0.0.0/16. In the consumer VPC, an application sends requests to an interface endpoint, a network interface with an address from the consumer's own subnet. AWS PrivateLink carries the traffic to the provider's endpoint service, which is fronted by a Network Load Balancer that forwards to the service's targets. Connections can be opened only from the consumer side, and the consumer reaches only that service, never the rest of the provider's network. Consumer VPC 10.0.0.0/16 Application [consumer] Interface endpoint [10.0.1.50] AWS PrivateLink Provider VPC 10.0.0.0/16 Network Load Balancer [endpoint service] Service [targets] Rest of the provider network: not reachable Connections open only from the consumer side. Both VPCs can use the same CIDR, because the consumer only ever addresses its own endpoint, and the provider sees traffic arriving from its load balancer.

Transit Gateway Route Tables as Segments

Trust boundary

One transit gateway whose route tables keep dev and prod apart.

A transit gateway whose route tables let prod and dev reach shared services but not each other Four attachments connect to one transit gateway: a prod VPC, a dev VPC, a shared services VPC, and a VPN to the on-premises network. The prod VPC and the VPN are associated with the prod route table, which has routes to prod, shared services, and on-premises. The dev VPC is associated with the dev route table, which has routes to dev and shared services only. The shared services VPC is associated with a shared route table with routes to every attachment. Because neither the prod nor the dev route table has a route to the other, prod and dev can't reach each other, even though both are attached to the same transit gateway. Prod VPC [prod route table] Dev VPC [dev route table] Shared services VPC [shared route table] VPN to on-premises [prod route table] Transit gateway [one Region] no route either way Each line is an attachment. The bracket names the route table it is associated with. Route tables Prod route table routes to prod, shared services, and on-premises Dev route table routes to dev and shared services Shared route table routes to every attachment

Direct Connect Virtual Interfaces

C4 · Deployment

One Direct Connect connection carrying public, private, and transit virtual interfaces.

How one Direct Connect connection carries public, private, and transit virtual interfaces to different AWS destinations A customer router in a data center connects to an AWS router at a Direct Connect location over a cross-connect. That one connection carries several virtual interfaces. A public virtual interface reaches AWS public endpoints such as S3. A private virtual interface reaches a Direct Connect gateway, which connects to virtual private gateways on VPCs in any Region, or attaches directly to a single virtual private gateway. A transit virtual interface reaches a Direct Connect gateway associated with transit gateways, which connect many VPCs. Data center Customer router Direct Connect location AWS router thick line: provider circuit, then a cross-connect inside the facility AWS public endpoints [S3, public service IPs] Direct Connect gateway Virtual private gateways [one VPC each, any Region] A private VIF can also attach directly to one gateway. Direct Connect gateway Transit gateways [many VPCs each] public VIF private VIF transit VIF One physical connection carries many virtual interfaces. Each is a VLAN with its own BGP session, and each reaches a different kind of destination.

Direct Connect With a VPN Backup

Flow

Two paths advertising the same prefixes, with each side preferring Direct Connect.

A Direct Connect path and a Site-to-Site VPN path to the same transit gateway, with Direct Connect preferred On-premises routers connect to a transit gateway over two paths: Direct Connect, the primary, and a Site-to-Site VPN over the internet, the backup. Both paths advertise the same on-premises prefixes using BGP. The on-premises routers prefer Direct Connect by local preference, and the transit gateway prefers Direct Connect routes over BGP VPN routes for the same prefix, so the VPN carries traffic only when the Direct Connect BGP session goes down. On-premises routers [prefer Direct Connect by local preference] Direct Connect [primary, BGP] Site-to-Site VPN [backup, BGP over the internet] Transit gateway [prefers Direct Connect over BGP VPN for the same prefix] Both paths advertise the same prefixes. The VPN carries traffic only when the Direct Connect BGP session goes down, so the VPN must use BGP rather than static routes, and must not advertise more specific prefixes than Direct Connect.

Placement Group Strategies

Structure

Cluster packs instances close; partition and spread keep them on separate racks.

How cluster, partition, and spread placement groups arrange instances on racks in one Availability Zone A cluster placement group places instances close together in one Availability Zone, on a high-bandwidth network segment, which lowers latency but leaves them more exposed to a shared hardware failure. A partition placement group divides instances into up to seven partitions per zone, and no two partitions share a rack, so a rack failure affects only one partition. A spread placement group puts each instance on its own rack, with at most seven running instances per zone. Cluster high-bandwidth segment Lowest latency between instances. More exposed to shared hardware failure. Partition P1 P2 P3 Partitions never share racks. Up to 7 per AZ, any number of instances. Spread One instance per rack. At most 7 running per AZ. Grey columns are racks, each with its own power and network. Boxes on them are instances. All three panels show one Availability Zone.

The Target Tracking Loop

C4 · Dynamic

An Auto Scaling group adjusting capacity to hold a metric at a target.

How a target tracking policy, an Auto Scaling group, its instances, and a CloudWatch metric form a feedback loop A target tracking policy sets the Auto Scaling group's desired capacity. The group launches or terminates instances across Availability Zones to match it. The instances publish a metric, such as average CPU utilization, to CloudWatch. The policy compares the metric to its target, for example 50 percent, and raises or lowers desired capacity, which closes the loop. Separately, health checks make the group replace any instance that fails them. Target tracking policy [keep average CPU at 50%] Auto Scaling group [desired capacity: 4] AZ a AZ b Instances CloudWatch metric [average CPU] sets desired launch or terminate publish metric compare to target failed health check: replace the instance The policy only moves desired capacity. The group's minimum and maximum bound it, and with a warmup set, new instances count only once ready.

IMDSv2 Tokens and the Hop Limit

Flow

Why containers need a metadata hop limit of 2 to receive an IMDSv2 token.

How the IMDSv2 token response reaches an application on the instance but not one in a container unless the hop limit is 2 An application on the instance requests an IMDSv2 session token from the instance metadata service with a PUT request, and the token comes back one network hop away. An application in a container on the same instance sends the same request through the container network bridge, so the response has to travel two hops. The token response is sent with an IP time-to-live equal to the hop limit, so with a hop limit of 1 it expires at the bridge and never reaches the container. A hop limit of 2 lets it through. EC2 instance Application [on the instance] Container Application [in a container] Container network bridge Instance metadata service [169.254.169.254] PUT for a token, reply 1 hop away reply 2 hops away hop limit 1: the reply expires at the bridge The token reply leaves with an IP time-to-live equal to the hop limit. Every later metadata GET must carry the token.

Execution Environments Over Time

Chart

Three requests, two environments: cold starts, reuse, and the concurrency they add up to.

How Lambda serves three requests with two execution environments Request 1 arrives with no environment available, so Environment 1 runs Init and then the handler: a cold start. Request 2 arrives while Environment 1 is still busy, so Lambda creates Environment 2, which also starts cold. After each invocation the environment is frozen and kept. Request 3 arrives after Request 1 finished and runs on the frozen Environment 1 with no Init: a warm start. The chart below counts busy environments over time, which is the function's concurrency: one, then two while both requests overlap, then one, zero, and one again. Init (cold start) handler running frozen, kept for reuse Environment 1 Init Request 1 Request 3 may be removed Environment 2 Init Request 2 may be removed time Request 1 arrives Request 2 arrives Request 3 arrives (cold) (Environment 1 busy: cold) (warm: no Init) Concurrency 2 1 0

Lambda's Three Invocation Models

Flow

Who waits, where retries happen, and where failed events go.

Synchronous, asynchronous, and event source mapping invocation of a Lambda function Synchronous: a caller such as API Gateway, an Application Load Balancer, a function URL, or the SDK sends an event and waits for the function's response or error. Lambda does not retry; the caller decides. Asynchronous: an event source such as S3, SNS, or EventBridge hands the event to Lambda's internal queue and gets a 202 acknowledgment at once. Lambda invokes the function from the queue, retries function errors twice and throttles until the maximum event age, and sends events that exhaust retries or age out to an on-failure destination. Event source mapping: a Lambda-managed poller reads batches from a queue or stream such as SQS, Kinesis, DynamoDB Streams, or Kafka and invokes the function synchronously with each batch. A failed batch is retried: SQS messages reappear after the visibility timeout, and a stream retries from the failed record while its shard waits. For streams, records that exhaust retries or age out go to an on-failure destination set on the mapping. Synchronous Caller [API Gateway, ALB, URL, SDK] Function event; the caller waits response or error No retries by Lambda. The caller decides. Asynchronous Event source [S3, SNS, EventBridge] Lambda's queue [internal] Function On-failure destination [SQS, SNS, S3, Lambda, EventBridge] event 202 at once invoke error: 2 retries · throttle: retried until the maximum age retries or maximum age used up Event source mapping Queue or stream [SQS, Kinesis, DynamoDB, Kafka] Event source mapping [Lambda-managed poller] Function poll batch sync invoke On-failure destination [streams: SQS, SNS, S3] streams: retries or record age used up failed batch retried: SQS messages reappear after the visibility timeout, and a stream retries from the failed record while its shard waits event flow acknowledgment retry or failure path

A VPC-Attached Function's Network Paths

C4 · Deployment

One Hyperplane ENI, and the three places traffic can go from it.

Network paths of a Lambda function attached to a VPC The function runs in Lambda's own network and reaches your VPC through a Hyperplane ENI in a private subnet, one ENI per combination of subnet and security group. From the ENI, traffic goes to private resources such as an RDS database directly, to AWS services such as S3, DynamoDB, or Secrets Manager through a VPC endpoint, and to the internet only through a NAT gateway in a public subnet and the internet gateway. A function that is not attached to a VPC reaches the internet and public AWS endpoints directly, but no private resources. Function [in Lambda's network] Your VPC Private subnet Public subnet Hyperplane ENI [per subnet + SG] RDS database [private resource] VPC endpoint [gateway or interface] NAT gateway AWS services [S3, DynamoDB, ...] Internet [via internet gateway] attached A function not attached to a VPC reaches the internet and public AWS endpoints directly, but no private resources. Attached, it has no internet route except through NAT, even when the ENI sits in a public subnet.

An ECS Service and Its Tasks

Structure

How a task definition, a service, its tasks, and a load balancer relate.

The relationship between an ECS task definition, service, tasks, cluster, and load balancer A task definition revision describes the containers: images, CPU, memory, ports, roles, and secrets. A service is configured with that revision and a desired count of four. The service starts four tasks from the revision inside a cluster, spread across two Availability Zones, on Fargate, EC2, or managed instance capacity, and replaces any task that stops or fails health checks. An Application Load Balancer's target group holds each task's IP address, health-checks the tasks, and routes requests to them. Task definition [revision 7] images, CPU, memory, ports, roles, secrets Service [desired count: 4] used by Application Load Balancer [target group: task IPs] Cluster AZ a AZ b Task [rev 7] Task [rev 7] Task [rev 7] Task [rev 7] awsvpc: each task has its own IP awsvpc: each task has its own IP capacity: Fargate, EC2 instances, or ECS Managed Instances starts and replaces tasks health checks, routes requests A new revision starts a deployment: the service launches tasks from it and stops the old ones.

EKS Control Plane and Data Plane

C4 · Deployment

Where the EKS control plane runs, and the node types it can manage.

An EKS cluster's control plane in an AWS-managed account and its data plane in your VPC and on-premises The EKS control plane, made up of the Kubernetes API server, scheduler, and etcd, runs across three Availability Zones in an AWS-managed account. It connects to your VPC through EKS network interfaces. Through them it talks to the data plane in your VPC: managed node groups of EC2 nodes you choose, EKS Auto Mode nodes that AWS runs, and Fargate pods that each get an isolated compute unit. Hybrid nodes on your own servers reach the same interfaces over a VPN or Direct Connect. AWS-managed account Control plane [API server, scheduler, etcd] across three Availability Zones Your VPC EKS network interfaces Managed node group [EC2 nodes you choose] Auto Mode nodes [nodes AWS runs] Fargate pods [isolated unit per pod] Your data center Hybrid nodes [your own servers] VPN or Direct Connect AWS runs the control plane and bills it per cluster-hour. Nodes and pods run in your VPC or on your own servers.

Storage Class Break-Even

Chart

Monthly cost of 1 TB by class as reads per month rise.

Monthly cost of storing 1 TB in S3 Standard, Standard-IA, and Glacier Instant Retrieval as the data is read more often A line chart. The horizontal axis is how many times the whole terabyte is read per month, from 0 to 2. The vertical axis is monthly cost in dollars. S3 Standard is flat at 23 dollars because reads carry no retrieval fee. Standard-IA starts at 12.50 dollars and rises 10 dollars per full read, crossing Standard at about one read a month. Glacier Instant Retrieval starts at 4 dollars and rises 30 dollars per full read, crossing Standard at about 0.6 reads a month and reaching 64 dollars at two reads. Request charges are ignored. $0 $20 $40 $60 0 0.5 1 1.5 2 Full reads of the terabyte per month Monthly cost for 1 TB Glacier IR costs more above ≈ 0.6 reads Standard-IA costs more above ≈ 1 read Standard Standard-IA Glacier Instant Retrieval Storage plus per-GB retrieval fees, US East (N. Virginia). Request charges are ignored.

Where EBS and EFS Live

C4 · Deployment

An EBS volume stays in one zone; an EFS file system spans the Region.

The scope of an EBS volume, an EBS snapshot, and an EFS file system A Region contains Availability Zones a and b. In zone a, instance 1 is attached to an EBS volume that exists only in zone a. A snapshot of that volume is stored at Region scope, and a new volume restored from it in zone b is attached to instance 2. An EFS file system is stored at Region scope across three or more zones. Each zone has one mount target, and each instance mounts the file system through the mount target in its own zone. Region Availability Zone a Instance 1 [EC2] Mount target [NFS on port 2049] EBS volume [exists in zone a only] Availability Zone b Instance 2 [EC2] EBS volume [restored from snapshot] Mount target [NFS on port 2049] EBS snapshot [Region scope] EFS file system [Region scope, data stored across three or more zones] Solid lines are block attachments and NFS paths to the file system. Dashed arrows are taking a snapshot and restoring it into another zone.

Three Ways RDS and Aurora Stay Available

C4 · Deployment

Where each high-availability option copies data, and which copies serve reads.

Multi-AZ DB instance, Multi-AZ DB cluster, and Aurora DB cluster compared Three panels. In a Multi-AZ DB instance deployment, a primary in zone a copies every write synchronously to a standby in zone b, each with its own EBS volume, and the standby serves no reads; failover takes 60 to 120 seconds. In a Multi-AZ DB cluster, a writer in zone a replicates to readers in zones b and c, and a commit waits for one reader to confirm; readers serve reads and failover takes under 35 seconds. In an Aurora DB cluster, a writer and two readers in three zones share one cluster volume that keeps six copies of the data across three zones; readers serve reads and failover usually takes under 60 seconds, often under 30. Multi-AZ DB instance AZ a Primary [read/write] [EBS volume] AZ b Standby [no reads] [EBS volume] synchronous copy of every write Standby takes over in 60–120 s. Reads need separate read replicas. Multi-AZ DB cluster AZ a Writer [read/write] [own storage] AZ b Reader [reads] [own storage] AZ c Reader [reads] [own storage] engine replication; a commit waits for one reader to confirm Readers serve reads and take over in under 35 s. Aurora DB cluster AZ a Writer [read/write] [compute] AZ b Reader [reads] [compute] AZ c Reader [reads] [compute] Cluster volume [six copies across three AZs] Readers serve reads and take over, usually in under 60 s, often under 30. Arrows are replication between instances. Plain lines connect Aurora instances to the one volume they share.

How DynamoDB Places Items and Indexes

Structure

The partition key picks each item's partition; a GSI re-keys a copy.

DynamoDB partitions, item collections, and a global secondary index An Orders table has partition key CustomerId and sort key OrderDate. DynamoDB hashes the partition key to choose a partition, so all orders for one customer form an item collection stored together and sorted by date. Partition 1 holds customer C123, partition 2 holds customers C456 and C789, and partition 3 holds C901. A global secondary index keyed on Status and OrderDate holds a second copy of the items, copied asynchronously, grouped into a SHIPPED collection and a PENDING collection on their own partitions. Orders table [partition key CustomerId, sort key OrderDate] hash(CustomerId) Partition 1 C123 Jan 15, Feb 20, Mar 3 Partition 2 C456 Jan 10 C789 Feb 2, Feb 28 Partition 3 C901 Mar 1 Global secondary index [partition key Status, sort key OrderDate] Index partition A SHIPPED C456, C123, C789, C123 Index partition B PENDING C789, C901, C123 copied asynchronously Items that share a partition key value form an item collection, stored together and sorted by the sort key. The index holds a second copy of the items under a different key, so it answers queries the table's key can't.

ElastiCache Cluster Mode Off and On

Structure

One shard with replicas, versus keys hashed into slots across shards.

Valkey or Redis OSS with cluster mode disabled and enabled With cluster mode disabled, one shard holds all the data: a primary node takes writes through the primary endpoint and replicates asynchronously to up to five replicas, which serve reads through the reader endpoint. With cluster mode enabled, each key is hashed to one of 16,384 slots, the slots are divided among shards, and each shard has its own primary and replicas. A cluster-aware client reads the slot map through the configuration endpoint, then sends each command directly to the primary of the shard that owns the key's slot. Cluster mode disabled Primary endpoint [writes] Reader endpoint [reads across replicas] One shard: all keys Primary [AZ a] Replica [AZ b] Replica [AZ c] Up to five replicas. Capacity is one node's memory. Cluster mode enabled Client [cluster-aware] Configuration endpoint [returns the slot map] reads slot map Primary Replica Shard 1 [slots 0–5460] Primary Replica Shard 2 [slots 5461–10922] Primary Replica Shard 3 [slots 10923–16383] Up to 500 shards. Each command goes to the shard owning slot CRC16(key) mod 16384. Solid arrows are client requests. The dotted arrow is slot discovery. Dashed arrows are asynchronous replication.

One Source of Truth, Derived Copies

Flow

One store takes every write, and three copies follow it.

A source of truth feeding derived copies The application writes only to the source of truth, which is Aurora, RDS, or DynamoDB. It reads a cache in ElastiCache first and fills it from the source on a miss, so a cached entry can be stale until its TTL expires. A search index in OpenSearch Service is fed from the source by a change-stream consumer or a managed ingestion pipeline and is never written directly. A Redshift warehouse is fed by a zero-ETL integration, seconds behind Aurora or RDS and 15 to 30 minutes behind DynamoDB. Application [writes one store] Source of truth [Aurora, RDS, or DynamoDB] Cache [ElastiCache] stale until its TTL expires Search index [OpenSearch Service] never written directly Warehouse [Redshift] seconds behind Aurora or RDS, 15 to 30 minutes behind DynamoDB writes read first; on a miss, load from the source and fill change-stream consumer or managed ingestion zero-ETL integration Solid arrows are application requests. Dashed arrows are replication from the source of truth.

An SQS Message's Lifecycle

State machine

A received message hides, then is deleted, reappears, or moves to a DLQ.

The states of a message in an SQS queue A producer sends a message and it becomes visible in the queue. A consumer's ReceiveMessage call returns it, raises its receive count by one, and hides it from other consumers for the visibility timeout. If the consumer deletes it before the timeout ends, it is gone. If the timeout expires first, the message becomes visible again for another receive. Once its receive count exceeds the redrive policy's maxReceiveCount, SQS moves it to the dead-letter queue instead. Producer Visible [any consumer can receive it] In flight [hidden from other consumers] Deleted Dead-letter queue [same account, Region, and type] SendMessage ReceiveMessage, count + 1 visibility timeout expires DeleteMessage receive count exceeds maxReceiveCount The visibility timeout defaults to 30 seconds and can be up to 12 hours. A consumer can extend it for a message it is still working on.

SNS to SQS Fanout

Flow

One topic, one queue and DLQ per consumer, beside a direct subscriber.

An SNS topic fanning out to SQS queues A publisher sends each message once to an SNS topic. The topic delivers a copy to three SQS queues, one each for the fulfillment, inventory, and email consumers. Each consumer reads only its own queue, and each queue has its own dead-letter queue for messages that fail repeatedly. A Lambda function subscribed directly to the topic, with no queue, receives the message by push and has only SNS's retries, with no backlog of its own. Publisher [publishes once] SNS topic [order-placed] Fulfillment queue [SQS] dead-letter queue Fulfillment service Inventory queue [SQS] dead-letter queue Inventory service Email queue [SQS] dead-letter queue Email service Lambda function [subscribed directly] SNS retries only, no backlog Solid pink arrows are SNS pushing a copy. Blue arrows are each consumer receiving from its own queue. Dashed arrows are repeated failures moving to a DLQ.

Who Owns the Routing on Each Event Bus

Structure

Classic rules live with the bus owner; subscribers live with each consumer.

Cross-account routing on a Classic event bus and on the Custom Event Bus On a Classic event bus, a producer in the platform account publishes to the bus, and the platform account owns one rule per consumer team, each sending matching events to a target in that team's account. On the Custom Event Bus, the platform account shares the bus through AWS RAM. The bus retains events. Each team account attaches its own subscriber to the shared bus, and each subscriber delivers to one target in that team's account. Classic event bus Platform account Producer Event bus [no retention unless archived] Rule for team A Rule for team B Team A account Queue Team B account Function Custom Event Bus Platform account Producer Shared event bus [retains 1 to 365 days] shared through AWS RAM Team A account Subscriber Queue Team B account Subscriber Function Dashed outlines are AWS accounts. On the left, the bus owner writes and changes every consumer's rule. On the right, each team creates and owns its own subscriber.

An Order Workflow with a Compensating Step

Flow

Three tasks in order, with retries and a catch that undoes the reservation.

The order state machine from the example definition The execution starts at ReserveInventory, a Lambda task that retries transient Lambda service errors up to six times. It moves on to ChargeCard, another Lambda task, then to SaveOrder, a DynamoDB putItem task that ends the execution. If ChargeCard fails with PaymentDeclined, its Catch sends the execution to ReleaseInventory, which undoes the reservation and retries the same errors, and then to OrderFailed, a Fail state that ends the execution as failed. start ReserveInventory [Task: Lambda] ChargeCard [Task: Lambda] SaveOrder [Task: DynamoDB putItem] succeeded ReleaseInventory [Task: Lambda] OrderFailed [Fail] Retry: Lambda service errors, up to 6 attempts Catch: PaymentDeclined Retry: same errors Solid arrows are each state's Next transition. The dashed arrow is the Catch path, taken only when ChargeCard fails with PaymentDeclined.

Waiting for a Callback

Flow

A task sends out a token and pauses until something sends it back.

The wait-for-callback pattern in Step Functions A Task state using the waitForTaskToken pattern sends a message containing a task token to an SQS approval queue, then the execution pauses. An approval application reads the message and shows the request to a person. While work is in progress it can call SendTaskHeartbeat with the token. When the person decides, the application calls SendTaskSuccess or SendTaskFailure with the token, and the execution resumes at the next state or at its error handling. Step Functions execution WaitForApproval [Task: sqs:sendMessage.waitForTaskToken] Next state resumes paused, no charge while it waits Approval queue [SQS] Approval application [shows the request to a person] message + task token receive SendTaskHeartbeat(token), while the work is in progress SendTaskSuccess(token, output) or SendTaskFailure(token, error) A missed heartbeat or the task's timeout fails the task instead.

Shards, Partition Keys, and Consumer Positions

Structure

Records ordered within a shard, read by consumers at their own pace.

A Kinesis data stream with three shards and two consumers Producers write records with a partition key. A hash of the key picks the shard, so every record with key A lands in shard 1, and keys B and D share shard 2 while C and E share shard 3. Within each shard, records are stored in order of their sequence numbers, oldest on the left. Two consumers read the same records independently, each keeping its own position in every shard, marked by short dashed lines. Consumer A has read almost to the newest records; consumer B is further behind. Records stay in the stream for the retention period, 24 hours by default and up to 365 days, whether or not anyone has read them, and expire after it. Producers [record + partition key] hash of the key picks the shard oldest newest (sequence numbers increase) Shard 1 A A A A A A A A A Shard 2 B D B B D B D D B Shard 3 C E E C E C C E C Consumer B's positions Consumer A's positions Retention window, 24 hours by default and up to 365 days. Records expire from the oldest end, read or not.

A StackSet Rolling Out Across Accounts and Regions

C4 · Dynamic

One template deployed to every account in an OU, a few at a time.

A service-managed StackSet deploying to an organizational unit A StackSet in the administrator account holds one template and its parameters. It targets the Workloads organizational unit in two Regions. With maximum concurrent accounts set to two, a failure tolerance of one, and Regions deployed in sequence, stack instances are created in us-east-1 two accounts at a time, each next account starting as soon as one finishes, and eu-west-1 starts when us-east-1 is done. Failures within a Region count against the failure tolerance, which stops the operation if exceeded. With automatic deployment on, account E, added to the OU later, receives its stack instances without any change to the StackSet. StackSet [administrator account] one template + parameters Workloads OU (service-managed, automatic deployment on) us-east-1 (first) two accounts at a time eu-west-1 (second) starts when us-east-1 finishes Account A stack instance stack instance Account B stack instance stack instance Account C stack instance stack instance Account D stack instance stack instance Account E added when the account joins added when the account joins Maximum concurrent accounts is 2 and failure tolerance is 1, so strict mode also runs two at a time. Each account starts as soon as a slot frees up.

How a Custom Resource Responds

C4 · Dynamic

CloudFormation waits for the provider's response in S3, not its return value.

The custom resource request and response protocol During a stack operation, CloudFormation sends the custom resource's provider, a Lambda function or SNS topic, a request with the request type (Create, Update, or Delete), the resource properties, and a pre-signed S3 response URL. The provider does the work, such as calling an external API, and then uploads its response to the pre-signed URL: SUCCESS or FAILED, a physical ID, and any attributes. CloudFormation reads the response from S3 and continues the stack operation. If no response arrives within the ServiceTimeout, one hour by default, the operation fails. CloudFormation [stack operation in progress] Provider [Lambda function or SNS topic] External system [the thing being managed] Pre-signed S3 URL [holds the response] 1 request Create, Update, or Delete properties + response URL 2 does the work 3 uploads the response SUCCESS or FAILED, physical ID, attributes for !GetAtt 4 reads it and continues no response within ServiceTimeout (1 hour by default): the operation fails

From CDK Code to Deployed Resources

Flow

Synthesis produces templates and assets; bootstrap roles deploy them.

How a CDK app is synthesized and deployed On a developer machine or in a pipeline, cdk synth runs the CDK app and writes a cloud assembly to cdk.out, containing a CloudFormation template per stack and the assets, such as Lambda code and container images. cdk deploy then uploads the assets to the bootstrap bucket and ECR repository using the file and image publishing roles, and hands the template to CloudFormation using the deployment role. CloudFormation creates the resources using the CloudFormation execution role, and resources such as Lambda functions reference their assets in the bucket. The bucket, repository, and roles belong to the bootstrap stack, CDKToolkit, deployed once per account and Region. Developer machine or pipeline CDK app [constructs in TypeScript, C#, ...] cdk synth Cloud assembly [cdk.out] a template per stack, plus assets Target account and Region (bootstrapped) Asset bucket and ECR repository [from the CDKToolkit stack] CloudFormation [deploys each stack] Your resources cdk deploy assets template execution role resources reference their assets Assets are uploaded with the file and image publishing roles, the template with the deployment role, and CloudFormation acts with the execution role. All belong to the bootstrap stack, deployed once per account and Region. The execution role has AdministratorAccess unless bootstrapped with narrower policies.

What the SAM Transform Generates

Structure

Each line of a SAM function or table becomes one or more CloudFormation resources, ten in all here.

How the SAM transform expands a function and a table The template declares OrdersFunction, an AWS::Serverless::Function, and OrdersTable, an AWS::Serverless::SimpleTable. When CloudFormation processes the template, the SAM transform expands each part into CloudFormation resources. The function itself becomes a Lambda function and an IAM execution role. AutoPublishAlias set to live becomes a Lambda version and a Lambda alias. The HttpApi event becomes an HTTP API, its default stage, and a Lambda permission that lets the API invoke the function. The SQS event becomes an event source mapping and adds queue-read permissions to the execution role. The connector granting Write access to OrdersTable becomes an IAM managed policy. The SimpleTable becomes an on-demand DynamoDB table. That is ten resources in all. Plain CloudFormation resources in the template, such as the queue itself, pass through the transform unchanged. What you write What CloudFormation deploys SAM transform OrdersFunction: Serverless::Function Lambda::Function IAM::Role AutoPublishAlias: live Lambda::Version Lambda::Alias Events: HttpApi ApiGatewayV2::Api ApiGatewayV2::Stage Lambda::Permission Events: SQS Lambda::EventSourceMapping + queue-read permissions on the role Connectors: Write to OrdersTable IAM::ManagedPolicy OrdersTable: Serverless::SimpleTable DynamoDB::Table on-demand capacity Plain CloudFormation resources in the same template, such as the queue the SQS event reads from, pass through the transform unchanged. Adding DeploymentPreference to the function would also generate a CodeDeploy application, a deployment group, and a service role.

A Pipeline That Deploys to Other Accounts

C4 · Deployment

The pipeline stays in a tooling account and assumes a role in each target account to deploy there.

Cross-account deployment from a tooling account A tooling account holds the pipeline, its CodeBuild projects, and the artifact bucket, which is encrypted with a customer managed KMS key. The pipeline stores artifacts in the bucket and runs builds in CodeBuild. For each target account, staging and production, the pipeline's service role assumes a cross-account role in that account. That role, which the target account trusts only for the pipeline's service role, reads the artifacts from the tooling account's bucket, with permission to use the key, and starts a CloudFormation deployment. CloudFormation creates the resources with its own execution role in the target account. The bucket policy and the key policy must allow each cross-account role to read the artifacts, and an AWS managed key can't be shared, so a cross-account pipeline needs a customer managed key. Tooling account Artifact bucket [customer managed KMS key] CodePipeline [runs as its service role] CodeBuild [build and test] stores artifacts runs builds Staging account Cross-account role [trusts the pipeline's role, reads artifacts, uses the key] CloudFormation [deploys with its execution role] starts Production account Cross-account role [trusts the pipeline's role, reads artifacts, uses the key] CloudFormation [deploys with its execution role] starts assumes a role in each account Each cross-account role reads its artifacts from the tooling account's bucket, which the bucket policy and the key policy must allow. An AWS managed key can't be shared with other accounts, so a cross-account pipeline needs a customer managed key.

Superseded and Queued Executions

C4 · Dynamic

In SUPERSEDED mode a newer waiting execution replaces an older one; in QUEUED mode both wait their turn.

How SUPERSEDED and QUEUED execution modes handle waiting executions Two copies of a pipeline with Build, Staging, and Production stages. In both, execution 1 is inside the Staging stage, which is locked, and executions 2 and 3 have finished Build and are waiting in front of Staging. In SUPERSEDED mode, the default, execution 3 replaces execution 2, which never enters Staging; when execution 1 finishes, execution 3 goes next, carrying execution 2's commits with it. In QUEUED mode, executions 2 and 3 wait in order, and each enters Staging and then Production in turn. SUPERSEDED (default) Build Staging [locked] #1 Production #2 #3 #3 replaces #2, which never enters Staging. When #1 finishes, #3 goes next, carrying #2's commits with it. QUEUED Build Staging [locked] #1 Production #3 #2 #2 and #3 wait in the order they arrived. Each enters Staging, and then Production, in turn.

The Order of EC2 Deployment Hooks

Flow

An in-place deployment behind a load balancer takes each instance out of service, replaces the application, and returns it.

Lifecycle events of an in-place CodeDeploy deployment to one instance behind a load balancer For each instance, an in-place deployment behind a load balancer runs thirteen lifecycle events in order, in three groups. First it takes the instance out of service: BeforeBlockTraffic, BlockTraffic, and AfterBlockTraffic. Then it replaces the application: ApplicationStop, DownloadBundle, BeforeInstall, Install, AfterInstall, ApplicationStart, and ValidateService. Finally it returns the instance to service: BeforeAllowTraffic, AllowTraffic, and AfterAllowTraffic. BlockTraffic, DownloadBundle, Install, and AllowTraffic are run by CodeDeploy itself and can't run scripts. BeforeBlockTraffic, AfterBlockTraffic, and ApplicationStop run scripts from the last successful revision's AppSpec file, and the remaining events run scripts from the new revision's. Without a load balancer, only the middle group runs. ApplicationStop is skipped on an instance's first deployment. Take the instance out of service BeforeBlockTraffic BlockTraffic (CodeDeploy) AfterBlockTraffic Replace the application ApplicationStop DownloadBundle (CodeDeploy) BeforeInstall Install (CodeDeploy) AfterInstall ApplicationStart ValidateService Return it to service BeforeAllowTraffic AllowTraffic (CodeDeploy) AfterAllowTraffic BeforeBlockTraffic, AfterBlockTraffic, and ApplicationStop run the last successful revision's scripts. The other solid events run the new revision's. Dashed events are run by CodeDeploy and can't run scripts. ApplicationStop is skipped on an instance's first deployment. Without a load balancer in the deployment group, only the middle column runs.

How Cognito Tokens Reach APIs and AWS

C4 · Dynamic

The user pool signs users in and issues tokens; the identity pool trades a token for AWS credentials.

Cognito user pool and identity pool token flow An app signs a user in to a Cognito user pool, which can federate sign-in to an external identity provider such as Google, Apple, or a SAML or OIDC provider. The user pool returns an ID token, an access token, and a refresh token. The app sends the access token to its own API, which verifies it, either in the API itself or in a service in front of it such as API Gateway. To call AWS services directly, the app sends the ID token to an identity pool, which returns temporary AWS credentials for an IAM role. The app then signs requests to AWS services such as S3 or DynamoDB with those credentials. An app that only calls its own API needs only the user pool. External identity provider [Google, Apple, SAML, OIDC] User pool [user directory and token issuer] Your app [web or mobile client] Your API [verifies the access token] Identity pool [trades a token for credentials] AWS service [S3, DynamoDB, ...] federated sign-in 1 sign in 2 ID, access, and refresh tokens 3 access token 6 requests signed with the credentials 4 ID token 5 temporary AWS credentials The user pool authenticates users and issues tokens. The identity pool exchanges a token for credentials from an IAM role. An app that only calls its own API needs only the user pool, steps 1 to 3.

Envelope Encryption with a KMS Key

C4 · Dynamic

KMS hands out a data key and its encrypted copy; the data is encrypted locally and stored with the encrypted key.

How envelope encryption uses a KMS key To encrypt, your application, or an AWS service such as S3 acting for you, calls GenerateDataKey on AWS KMS, naming a KMS key and an encryption context. KMS returns a new data key twice: in plaintext, and encrypted under the KMS key. The application encrypts the data locally with the plaintext data key, discards that key, and stores the encrypted data together with the encrypted data key. To read the data later, the application loads the encrypted data key, sends it to KMS in a Decrypt call with the same encryption context, gets the plaintext data key back, and decrypts the data locally. The KMS key itself never leaves KMS. Every GenerateDataKey and Decrypt call counts against the account's KMS request quota and is logged in CloudTrail. Your application [or an AWS service such as S3] AWS KMS KMS key [never leaves KMS] 1 GenerateDataKey, or 5 Decrypt to read 2 or 6 plaintext data key (GenerateDataKey also returns an encrypted copy) Stored together Encrypted data Encrypted data key 3 encrypt the data locally, discard the plaintext key, store both 4 to read, load the encrypted data key, 5 send it to Decrypt, 6 get the plaintext data key back, and decrypt locally Only data keys travel to and from KMS. Every GenerateDataKey and Decrypt call counts against the account's KMS request quota and appears in CloudTrail, which is why S3 Bucket Keys and data key caching exist to reduce them.

How a Web ACL Evaluates a Request

Flow

Rules run in priority order; the first Allow or Block ends evaluation, while Count lets it continue.

Rule evaluation order in an AWS WAF web ACL A request enters the web ACL and meets its rules in priority order, lowest number first. In this example, rule 0 is an IP allow list whose Allow action forwards matching requests immediately. Rule 1 is a rate-based rule that blocks sources over the limit. Rule 2 is a managed rule group with some rules set to Count, which records matches and adds labels but lets the request continue; its other rules can still block. Rule 3 blocks requests that carry a label added earlier. A request that no rule stops reaches the web ACL's default action, here Allow. Allow, Block, CAPTCHA, and Challenge end evaluation when they apply; Count never does. Request 0 IP allow list [action: Allow] 1 Rate-based rule [action: Block] 2 Managed rules [some set to Count] 3 Label match [action: Block] Default action [Allow] no match, or Count: continue to the next rule Allow allowed through Block 403 or a custom response Count labels, continue Block other rules Block if an earlier rule labeled it Allow nothing stopped it Rules run in priority order, lowest number first. Allow, Block, CAPTCHA, and Challenge end evaluation when they apply. Count records the match and lets the request move on. Any matching rule can add labels for later rules.

Audit Logging Across an Organization

C4 · Deployment

An organization trail and Config recorders in every account feed one log archive bucket and one aggregator.

Organization-wide CloudTrail and Config layout The management account, or a delegated administrator, owns an organization trail, which applies to every account and Region in the organization, including accounts added later. In every account and Region, CloudTrail records API activity and an AWS Config recorder records resource configurations. CloudTrail delivers log files, and Config delivers configuration history and snapshots, to one S3 bucket in a dedicated log archive account, encrypted with a KMS key and protected from deletion. A Config aggregator in a security account, registered as a delegated administrator, collects configuration and compliance data from every account and Region. The organization trail covers new accounts automatically, but Config recorders must be deployed to new accounts through Control Tower, StackSets, or Systems Manager Quick Setup. Management account [owns the organization trail] Every account and Region CloudTrail [API activity, via the organization trail] AWS Config recorder [resource configurations] trail covers all accounts, including new ones Log archive account S3 bucket [trail logs and Config history, KMS-encrypted, deletion blocked] Security account (delegated administrator) Config aggregator [compliance across accounts and Regions] log files history and snapshots configuration and compliance data The organization trail reaches new accounts automatically. Config recorders don't, so they're deployed to each new account and Region through Control Tower, CloudFormation StackSets, or Systems Manager Quick Setup.

Security Findings Across an Organization

C4 · Deployment

Findings from every account and Region collected in one home Region.

Organization-wide flow of security findings In every Region, GuardDuty, Security Hub CSPM, Inspector, and Macie produce findings in each member account. In each Region, those findings go to Security Hub in a security account that the management account has made the delegated administrator, the same account in every Region. Security Hub CSPM is both a source of findings in each member account and, with Security Hub, a hub that collects them. Findings from linked Regions are replicated to one home Region, where the dashboards cover all accounts and Regions and where automation rules and ticketing are defined. From the home Region, findings are routed through EventBridge to notification and containment, and Security Hub opens Jira or ServiceNow tickets. GuardDuty also publishes its own findings to EventBridge in each Region, which the figure leaves out. Each service must still be enabled, and is still billed, in every Region; aggregation copies data but enables nothing. Every member account Security account (delegated administrator) Response Linked Region Home Region GuardDuty · Security Hub CSPM Inspector · Macie [findings in this account and Region] Security Hub [and Security Hub CSPM] all members, this Region findings GuardDuty · Security Hub CSPM Inspector · Macie [findings in this account and Region] Security Hub [and Security Hub CSPM] all members, all Regions dashboards, automation rules, ticketing findings replicated EventBridge [notify, contain] Jira / ServiceNow [Security Hub tickets] Aggregation copies data but enables nothing. Each service stays enabled, and billed, in every Region it monitors. The management account designates the delegated administrator, which must be the same account in every Region.

Cross-Account Observability and Log Centralization

C4 · Deployment

One reads other accounts' data in place, the other copies logs.

CloudWatch cross-account observability compared with log centralization With cross-account observability, source accounts in one Region create links to a sink in a monitoring account in the same Region. The metrics, logs, and traces stay in the source accounts, which keep paying for them, and the monitoring account's dashboards, queries, and alarms read them in place. With log centralization, rules replicate new log events from source accounts in several Regions into centralized log groups in one destination account and Region, with an optional second copy in a backup Region. Events that arrived before the rule was created are not copied. Cross-account observability, within one Region Source accounts [metrics, logs, traces stay here] each pays for its own data Monitoring account [sink] dashboards, queries, and alarms link grants access reads data in place Log centralization, across Regions Source accounts, Region A [new log events] Source accounts, Region B [new log events] Destination account Destination Region [centralized log groups] Backup Region [optional second copy] copied by rule copied by rule data copied access only, data stays in the source account

One Trace as a Timeline

C4 · Dynamic

Segments and subsegments of one request across two services, over time.

An X-Ray trace shown as a timeline of segments and subsegments A timeline from 0 to 640 milliseconds. API Gateway records a segment for the whole request. The orders service records its own segment, containing subsegments for a DynamoDB GetItem call, an HTTP POST to the payments service, and an SQS SendMessage call. DynamoDB, SQS, and the card network API send no segments, so X-Ray infers their nodes from the callers' subsegments. The payments service records its own segment, which starts shortly after the orders service's POST subsegment begins and ends shortly before it ends; the difference is time in transit. Inside the payments segment, a subsegment times the call to an external card network API. API Gateway orders DynamoDB GetItem POST /payments payments card network API SQS SendMessage in transit in transit 0 ms 100 200 300 400 500 600 segment, sent by the service itself subsegment, a call timed by its caller DynamoDB, SQS, and the card API send no segments, so X-Ray infers their nodes from these subsegments

How a Session Manager Connection Is Made

C4 · Dynamic

Both sides connect out to Systems Manager, so the node needs no inbound rule.

Session Manager connection path An operator starts a session from the console or the AWS CLI, which calls Systems Manager over HTTPS. Systems Manager checks the operator's IAM permissions. SSM Agent on a managed node in a private subnet has already connected out to Systems Manager's ssm and ssmmessages endpoints over HTTPS on port 443, through interface VPC endpoints or a NAT gateway. Systems Manager relays the session between the two outbound connections, so the node's security group needs no inbound rule and the node needs no public IP address or SSH key. If session logging is configured, SSM Agent sends the session transcript from the node to S3 or CloudWatch Logs. Operator [console or AWS CLI] Systems Manager [ssm and ssmmessages endpoints] checks IAM, relays the session VPC, private subnet Managed node [SSM Agent] no inbound rule, no public IP start session, HTTPS agent connects out, HTTPS 443, through VPC endpoints or NAT S3 or CloudWatch Logs [session logs, if configured] transcript Arrows point from the side that opens each connection. Session data flows both ways over the two connections Systems Manager relays.

How an Hourly Commitment Covers a Day

Chart

Usage under the commitment is discounted, above it is On-Demand, and unused commitment is still billed.

A Savings Plans commitment applied to one day of usage A chart of one day of hourly compute usage, measured in On-Demand dollars per hour, from midnight to 11 PM. Usage is lowest overnight, around 12 to 14 dollars an hour, rises to about 27 dollars an hour at midday, and falls again in the evening. A horizontal line marks the commitment, expressed as the On-Demand usage it covers, at 15 dollars an hour. Usage below the line is billed at the discounted Savings Plans rate. Usage above the line, during the day, is billed at On-Demand rates. In the early morning and late evening, usage falls below the line, and the unused part of the commitment is still billed. $0 $10 $20 $30 midnight 6 AM noon 6 PM 11 PM Hourly usage, measured at On-Demand prices, over one day Covered by the commitment, billed at the discounted rate Above the commitment: billed On-Demand commitment Unused commitment: billed even though nothing ran on it Commitment, as the On-Demand usage it pays for

Pulling an Image from a Private Subnet

C4 · Deployment

Token and manifest through two interface endpoints, layers through S3.

Private image pull path from a private subnet to Amazon ECR A task or node in a private subnet with no NAT gateway pulls an image in three kinds of request. It calls the ecr.api interface VPC endpoint for an authorization token and other ECR API calls. It calls the ecr.dkr interface VPC endpoint, with private DNS enabled, to read the image manifest from the registry. It then downloads each image layer from an Amazon S3 bucket owned by ECR, through an S3 gateway endpoint attached to the subnet's route table. All three services are in the same Region as the VPC. VPC, private subnet (no NAT gateway) Task or node [ECS, EKS, CodeBuild] ecr.api endpoint [interface endpoint] ecr.dkr endpoint [interface, private DNS on] S3 gateway endpoint [route table entry] Amazon ECR [same Region as the VPC] ECR API authorization token, API calls Registry image manifest Amazon S3 [layer bucket owned by ECR] 1. token 2. manifest 3. layers

A Call Through ECS Service Connect

C4 · Dynamic

A short name, resolved by the caller's proxy, to a healthy task's proxy.

A request between two ECS services through Service Connect Two ECS services, checkout and orders, belong to the same Service Connect namespace, an AWS Cloud Map namespace. Every task has an application container and a Service Connect proxy container. The orders service publishes the endpoint http://orders:8080 in the namespace, and the namespace tells each proxy which tasks back that endpoint. The checkout application calls http://orders:8080, which goes to the proxy in its own task. That proxy picks a healthy orders task and sends the request to the proxy in that task, retrying or ejecting tasks that fail. The receiving proxy passes the request to the orders application in the same task. Both proxies send request metrics to CloudWatch. Service Connect namespace (an AWS Cloud Map namespace) Cloud Map namespace [orders:8080 → orders tasks] checkout service task checkout app [container] Proxy [Service Connect] orders service task 1 Proxy orders app task 2 Proxy orders app 1. calls http://orders:8080, which reaches its own proxy 2. picks a healthy task, retries or ejects failures 3. hands the request to its app endpoints CloudWatch metrics metrics

How a Pod Gets Credentials with EKS Pod Identity

C4 · Dynamic

SDK to node agent to EKS Auth, with an optional hop into another account.

EKS Pod Identity credential path A pod whose service account has a Pod Identity association gets environment variables that point the AWS SDK's container credential provider at the Pod Identity agent, a DaemonSet on the same node listening on a link-local address. The SDK asks the agent for credentials, presenting the pod's service account token. The agent calls the EKS Auth service's AssumeRoleForPodIdentity action. EKS Auth looks up the association for the cluster, namespace, and service account and assumes the associated IAM role in the cluster's account, whose trust policy names the pods.eks.amazonaws.com service principal. If the association also names a target role in another account, EKS Pod Identity assumes that role through role chaining, and the pod receives the target role's credentials. Credentials return along the same path to the SDK. EKS node (Linux EC2) Pod [app + AWS SDK] env vars point the SDK at the agent Pod Identity agent [DaemonSet, 169.254.170.23] serves pods on this node only 1. request credentials credentials EKS Auth [AssumeRoleForPodIdentity] finds the association 2. pod token Cluster account IAM role [trusts pods.eks.amazonaws.com] bound by the association Resource account (optional) Target role [trusts the cluster-account role] its credentials go to the pod 3. assume role 4. role chaining, if a target role is set Dashed arrow: credentials returning to the SDK. Dashed box: present only when the association names a target role.

Metadata and Data Paths in an S3 Data Lake

Structure

Engines look up tables in the Data Catalog, then read S3 directly.

Glue Data Catalog as the metadata layer over S3 Four engines, Athena, Redshift Spectrum, Amazon EMR, and Glue ETL jobs, each look up a table in the AWS Glue Data Catalog, which returns the schema, format, partitions, and S3 location. Each engine then reads the files directly from the S3 data lake. Data never passes through the catalog. Crawlers read S3 and jobs that write data to S3, and both update table and partition definitions in the catalog. Lake Formation, when used, grants access at the table, column, and row level on the catalog and issues the credentials engines use for the S3 read. Engines Athena Redshift Spectrum Amazon EMR Glue ETL jobs Glue Data Catalog [Regional, metadata only] schema, format, partitions, S3 location S3 data lake [Parquet, ORC, JSON, CSV files] Iceberg tables add metadata files Crawlers and writing jobs touch S3, update the catalog Lake Formation [optional] table, column, row grants grants access S3 credentials 1. look up the table 2. read the files points to Every engine takes both paths, and only metadata passes through the catalog.

How Redshift Spreads a Query Across Slices

Structure

A leader node plans, slices work in parallel, and managed storage sits beneath.

Redshift massively parallel processing architecture A client sends SQL to the leader node and receives results from it. The leader node plans the query and sends steps to two compute nodes. Each compute node has two slices. The orders and order_lines tables are both distributed by order_id, so rows with the same order_id sit on the same slice and each slice joins its own rows without moving data. A table distributed on a different key would need its rows redistributed between nodes over the network before the join. Each compute node caches hot data on local SSD, and all table data is stored durably in Redshift Managed Storage, backed by S3, independent of the number of nodes. The leader node combines the slices' results and returns them to the client. Client [BI tool, SQL] Leader node plans, distributes, combines query and results Compute node 1 (local SSD cache) Slice 1 orders: 3, 41, 77 order_lines: 3, 41, 77 [joins its own rows] Slice 2 orders: 12, 19, 64 order_lines: 12, 19, 64 [joins its own rows] Compute node 2 (local SSD cache) Slice 3 orders: 8, 33, 50 order_lines: 8, 33, 50 [joins its own rows] Slice 4 orders: 25, 26, 91 order_lines: 25, 26, 91 [joins its own rows] steps out, results back Redshift Managed Storage [durable, S3-backed, grows independently of node count] blocks cached and written back Numbers are order_id values. Both tables use DISTKEY(order_id), so matching rows share a slice. A table distributed on another key would have its rows redistributed between nodes before the join.

Embedding a Dashboard for Anonymous Users

C4 · Dynamic

Your backend vouches for the viewer; Quick Sight applies its tags as row filters.

Anonymous embedding flow for an Amazon Quick Sight dashboard A user signs in to your application through its own authentication. The browser asks your application's backend for a dashboard. The backend, using an IAM role, calls the Quick Sight GenerateEmbedUrlForAnonymousUser API with the dashboard and session tags derived from its own authenticated session, such as the tenant ID. Quick Sight returns a short-lived embed URL. The backend passes the URL to the browser, which loads the dashboard in a frame through the embedding SDK from an allowlisted domain. Quick Sight serves the dashboard and applies the session tags as row-level security filters on the dataset, so the viewer sees only their tenant's rows. Each 30-minute session draws on capacity pricing. Browser [your app's frontend] dashboard in a frame, allowlisted domain Your application Backend [IAM role] authenticates the user, derives tags: tenant = acme Amazon Quick Sight [Enterprise edition] applies tags as row-level security on the dataset 1. signed-in request 2. embed URL request + tags 3. short-lived URL 4. embed URL 5. load the dashboard, filtered to tenant = acme Quick Sight trusts the tags the backend sends, so they must come from the backend's own authenticated session.

One Catalog Over Lake, Tables, and Warehouse

Structure

Engines read every store through one catalog, with Lake Formation checking access.

Lakehouse architecture of Amazon SageMaker Query and processing engines, Athena, Redshift, Spark on EMR and Glue, and other Apache Iceberg engines connecting through an Iceberg REST endpoint, all look up tables in one catalog layer built on the AWS Glue Data Catalog, with AWS Lake Formation checking permissions and vending credentials. Beneath the catalog layer sit four kinds of catalog: an S3 data lake of files in general purpose buckets, S3 table buckets holding managed Iceberg tables, tables stored in Redshift Managed Storage, and federated sources such as other databases that are queried in place. Engines read each store directly after the catalog lookup, so one copy of each table serves every engine. Engines Athena Redshift Spark [EMR, Glue] Other Iceberg engines [Iceberg REST endpoint] Catalog layer: AWS Glue Data Catalog + AWS Lake Formation table definitions for every store, grants down to rows and cells, credentials vended for S3 data 1. look up, authorize 2. read directly Catalogs over each store S3 data lake [general purpose buckets] Parquet files, Iceberg S3 Tables [table buckets] managed Iceberg tables Redshift [Redshift Managed Storage] warehouse tables Federated sources [other databases] queried in place catalog describes each store Every engine takes the same two steps shown for Athena, so one copy of each table serves every engine.

The Client-Side Tool-Use Loop

C4 · Dynamic

The model asks, your code runs the tool, and the loop repeats until an answer.

Tool use between an application and a Bedrock model Your application sends the Bedrock Converse API a request containing the user's message and a list of tools, each described with a name and a JSON schema. The model responds with a tool-use request naming a tool and its arguments instead of an answer. Your application runs the tool, such as calling an orders API or a Lambda function, under its own permissions, and sends the tool result back in the next request along with the conversation so far. The model either asks for another tool or returns the final answer. The loop repeats until the model stops asking for tools. With client-side tool use the model never calls the tool itself, and your code decides whether and how each call runs. Your application [holds tools and permissions] Model on Bedrock [Converse API] Tool [orders API, Lambda] 1. messages + tool schemas 2. tool-use request: name, arguments 3. run the tool 4. tool result + conversation so far 5. another tool-use request (back to 3), or the final answer In client-side tool use the model never calls the tool. Your code decides whether each call runs, with what permissions.

Several Models on One SageMaker AI Endpoint

Structure

Each inference component reserves its own CPU, GPU, and memory and scales its own copies.

Inference components sharing a SageMaker AI endpoint An application calls InvokeEndpoint and names the inference component it wants. The endpoint has one production variant with managed instance scaling, running two ml.g5.xlarge instances, each with four vCPUs, one GPU, and 16 GB of memory. A ranker component needs one GPU, so each instance holds one of its two copies. A churn-model component needs one vCPU and 2 GB, and its three copies sit where capacity is free, two on the first instance and one on the second, which leaves spare capacity on the second instance. A third component on the same endpoint, fraud-model, is scaled to zero copies and uses no capacity until it is scaled out again. Each component scales its own copy count, and managed instance scaling adds or removes instances to fit the copies. Application [InvokeEndpoint] Each request names the inference component to call Endpoint: one production variant [managed instance scaling adds or removes instances to fit the copies] Instance 1: ml.g5.xlarge [4 vCPU, 1 GPU, 16 GB] ranker, copy 1 [1 GPU, 8 GB] churn-model, copy 1 [1 vCPU, 2 GB] churn-model, copy 2 [1 vCPU, 2 GB] Instance 2: ml.g5.xlarge [4 vCPU, 1 GPU, 16 GB] ranker, copy 2 [1 GPU, 8 GB] churn-model, copy 3 [1 vCPU, 2 GB] spare capacity for another copy fraud-model, 0 copies [a component scaled to zero stays on the endpoint and uses no capacity] Each inference component sets its model's CPU, GPU, and memory and scales its own copy count. With every component at zero copies, the endpoint can scale to zero instances, and the next request fails until an instance starts, which takes several minutes.

Move Groups and Migration Waves

Structure

Dependencies bind applications into move groups, and move groups fill waves.

Applications grouped into move groups and scheduled into migration waves Shared services such as the directory and DNS are built in AWS before wave 1 and belong to no move group. Three move groups follow. Move group C holds a team wiki with no dependencies. Move group B holds an HR application and a payroll application that share one owner and one patch window. Move group A holds an orders application and a billing application that share an order database. Group C moves in wave 1 with two test-environment servers, group B in wave 2 with six servers, and group A, in production, in wave 3 with eighteen servers. Later waves grow as the process becomes repeatable. Shared services, built in AWS before wave 1 Directory (domain controller) and DNS. Every application depends on them, so they belong to no move group. Move group C [no dependencies] Team wiki Move group B [same owner, same patch window] HR app Payroll app one cutover window for both Move group A [shared database] Orders app Billing app Order database Wave 1 2 servers, test environment Wave 2 6 servers Wave 3 18 servers, production [later waves grow as the process becomes repeatable]

Server Replication with AWS Transform MGN

C4 · Deployment

Blocks flow to a staging subnet; launch converts them into an EC2 instance.

AWS Transform MGN replication path from a source server to a launched EC2 instance A source server in a data center or another cloud runs the AWS Replication Agent. The agent talks to the AWS Transform MGN service endpoint over TCP 443 for control and sends replicated disk blocks over TCP 1500 to a replication server, a small EC2 instance in a staging area subnet in your VPC in the target Region. The replication server writes the blocks to staging EBS volumes and also reports to the service over TCP 443. When a test or cutover instance is launched, MGN snapshots the staging volumes and a conversion server prepares copies to boot on AWS, and the instance starts in a separate launch subnet. Source environment [data center or other cloud] Source server [AWS Replication Agent] AWS, target Region AWS Transform MGN [service endpoint] Staging area subnet, your VPC Replication server [small EC2 instance] Staging EBS volumes Conversion server [runs at each launch] Launch subnet, your VPC Test or cutover instance [EC2, boots natively] TCP 1500 disk blocks TCP 443 TCP 443 snapshot
C4 · Deployment

Local traffic stays on site; the service link carries management and VPC traffic.

An AWS Outpost at a customer site connected to its parent AWS Region An AWS Outpost at the customer's site is an extension of one Availability Zone in its parent Region. Its subnet belongs to the same VPC as subnets in that Availability Zone and runs EC2 instances, EBS volumes, S3 on Outposts, and services such as ECS, EKS nodes, and RDS. Traffic between the Outpost and the on-premises network goes through the local gateway and stays on site. The service link connects the Outpost to the parent Region, carrying VPC traffic to subnets in the Region and management traffic to the Regional control plane, which handles EC2 and EBS APIs, IAM, and CloudWatch. Launching or stopping instances needs the control plane. Your site AWS Outpost [extension of one Availability Zone] Outpost subnet EC2 instances, EBS volumes S3 on Outposts ECS, EKS nodes, RDS [same VPC as the Region subnets] On-premises network [local systems and users] local gateway Parent AWS Region VPC subnets in the parent Availability Zone [instances and services in the Region] Regional control plane EC2 and EBS APIs, IAM, CloudWatch [launching or stopping instances needs it] service link VPC traffic management traffic

Single-Writer and Multi-Active Replication

Structure

Where writes go in each pattern, and which way replication flows.

Single-writer and multi-active cross-Region replication patterns Two patterns side by side. In the single-writer pattern, the application in Region A reads and writes a primary database. The application in Region B reads a local read replica, but sends its writes across Regions to the primary in Region A. The primary replicates to the replica asynchronously. In the multi-active pattern, the application in each Region reads and writes its own local replica, and the two replicas replicate to each other asynchronously in both directions. When the same item is written in both Regions at once, the last writer wins. Single writer: read local, write global Region A Application Primary [reads and writes] reads, writes Region B Application Read replica [reads only] reads writes async replication Multi-active: write local Region A Application Replica [reads and writes] reads, writes Region B Application Replica [reads and writes] reads, writes async replication both ways [same item written in both Regions: last writer wins]

Backups Kept Out of Reach

C4 · Deployment

Backups copied to a locked vault in another account and Region, restored into a recovery account.

AWS Backup copies isolated across accounts and Regions In the primary Region, a backup plan in the workload account backs up production resources into a backup vault protected by Vault Lock. A copy job copies the recovery points to a logically air-gapped vault owned by a separate backup account in the recovery Region, where they are locked in compliance mode and encrypted with an AWS-owned key by default or a customer managed key. The air-gapped vault is shared through AWS Resource Access Manager with a recovery account in the same Region, which restores directly from it and deploys the rest of the stack from infrastructure as code. Primary Region Production resources [workload account] Backup vault [workload account, Vault Lock] backup plan runs on schedule Recovery Region Logically air-gapped vault [dedicated backup account, locked] Restored resources and stack [recovery account, stack from infrastructure as code] copy job restore through a Resource Access Manager share

Found this useful? Share it:

Share on LinkedIn