AWS Cloud Practitioner 03: Compute

AWS Cloud Practitioner 03: Compute

AWS offers compute in many forms. It comes as a virtual machine that we rent by runtime, as a container without a server of our own, or as a function that runs only when an event arrives. The exam rarely asks about configuration details, but very often about which service and which purchase option fit a described scenario. We build up that mapping in this part, and at the end we create a Lambda function in our own account and measure its cold start.

EC2 as a toolkit for virtual servers

Amazon EC2 (Elastic Compute Cloud) is the classic way to get compute on AWS. An instance is made up of a few building blocks. The AMI (Amazon Machine Image) provides the operating system and preinstalled software, the instance type determines CPU and memory, and on top come storage, a security group as a firewall and optionally user data. User data is a boot script that runs once with root permissions when the instance first starts, for example to install packages.

AMIs come from several sources. AWS provides public AMIs, we create our own from a configured instance (Part 04), and in the AWS Marketplace third-party vendors offer preconfigured AMIs, some with paid software.

Instance types follow a fixed naming scheme. In m5.2xlarge, m stands for the class, 5 for the generation and 2xlarge for the size within the class. For the exam it is enough to match the families to their use cases.

FamilyTypical use
General Purposebalanced load, web servers, code repositories, small to medium databases
Compute Optimizedbatch processing, media transcoding, HPC, dedicated game servers
Memory Optimizedin-memory databases, analysis of large data sets in RAM
Storage Optimizedhigh local I/O, databases with high throughput, data processing

On top of that comes Accelerated Computing with GPUs or other accelerators, for graphics and machine learning for example.

The security group knows only allow rules and is stateful. An allowed inbound connection can therefore reply automatically, without us needing an outbound rule for it. By default, inbound traffic is blocked and outbound traffic is open. This gives a popular diagnostic question. If a connection attempt runs into a timeout, the security group is usually blocking it. If you get connection refused instead, the packet arrived, but no application is listening on the port.

A few ports are worth knowing by heart: 22 for SSH and SFTP, 21 for FTP, 80 for HTTP, 443 for HTTPS and 3389 for RDP (Windows Remote Desktop). EC2 Instance Connect opens an SSH session directly in the browser, but it also needs port 22 in the security group.

With EC2, the Shared Responsibility Model leaves a lot of the work with us. We maintain the guest operating system including security patches, the installed software, the security group rules, permissions through IAM and our data. AWS is responsible for hardware, network and data centers, which includes replacing faulty servers.

Anyone who runs a database on EC2 themselves takes on patches, backups and high availability. The Exam Guide expects us to be able to weigh this option against a managed database (Task 3.4). We know the shift in responsibility from the Shared Responsibility Model in Part 01, and the managed databases follow in Part 05.

Purchase options: discount in exchange for commitment

The same instance can cost very different amounts, depending on how we buy it. In Task 4.1 the Exam Guide names seven purchase options. The more we commit, or the more uncertainty we accept, the bigger the discount compared with On-Demand.

Bar chart of maximum discounts compared with On-Demand: On-Demand 0 percent, Convertible RI and Compute Savings Plan 66 percent, Standard RI and EC2 Instance Savings Plan 72 percent, Spot 90 percent

The maximum values come from the Savings Plans documentation and the EC2 pricing page (as of October 25, 2026). They are snapshots that AWS can change at any time, and the exam doesn’t ask for the percentages but for the order and the fitting scenario.

OptionWhen it fits
On-Demandshort, unpredictable load; Linux and Windows are billed per second, with a minimum of 60 seconds
Reserved Instancessteady load over 1 or 3 years, such as a database; payment No, Partial or All Upfront; Standard RIs can be resold on the RI Marketplace, Convertible RIs cannot
Savings Planssteady load with a commitment to an hourly amount instead of to an instance; Compute Savings Plans also apply to Fargate and Lambda
Spot Instancesfault-tolerant work such as batch, analysis, image processing; AWS can reclaim the instance at any time, so never for critical jobs or databases
Dedicated Hosta whole physical server for us, with visibility into sockets and cores; for licenses tied to sockets or cores (BYOL), and compliance
Dedicated Instancehardware that we share with no other AWS customer, but without control over placement on the host
Capacity Reservationguaranteed capacity in a specific AZ; costs the On-Demand price even if we don’t use it, with no term commitment

According to the Exam Guide, Reserved Instances are flexible within limits and are shared between accounts in AWS Organizations through consolidated billing (Task 4.1). Also, Savings Plans don’t guarantee capacity. Anyone who needs both combines them with an On-Demand Capacity Reservation, according to the AWS documentation. Confusing a discount with a capacity guarantee is a typical trap.

Anyone bringing their own licenses (BYOL) to Dedicated Hosts keeps track of them with AWS License Manager. The service manages software licenses across AWS and on premises and tracks how many of them are in use.

Elastic Load Balancing distributes, Auto Scaling adjusts the number

A single instance is a single point of failure. Once we spread several instances across several AZs, we need a shared entry point in front of them. That is the job of Elastic Load Balancing (ELB). A load balancer distributes the requests, uses a health check to see which instances are healthy, can terminate SSL/TLS and provides a single DNS name that clients talk to.

AWS offers four types, which differ in the network layer they decide on.

Four load balancer types as layers: Application Load Balancer on layer 7 for HTTP, HTTPS and gRPC with routing by path and host, Network Load Balancer on layer 4 for TCP, UDP and TLS, Gateway Load Balancer on layer 3 for firewalls and appliances, Classic Load Balancer greyed out as the previous generation

TypeLayerTypical keyword
Application Load Balancer (ALB)Layer 7HTTP/HTTPS, web applications, routing by path or host
Network Load Balancer (NLB)Layer 4TCP/UDP, extreme performance
Gateway Load Balancer (GWLB)Layer 3firewalls and other virtual appliances from third parties
Classic Load Balancer (CLB)older generationmigration to ALB or NLB recommended

The Classic Load Balancer still exists. On August 15, 2022, only EC2-Classic, the old network platform, ended, and with it the CLBs that ran in it. CLBs in a VPC continue to exist, but AWS recommends migrating to ALB or NLB.

All types are reachable through their DNS name; a custom domain goes in front via a Route 53 alias (Part 06). The Network Load Balancer additionally has one static IP address per AZ, and a public NLB can use an Elastic IP. That is why we can also address it directly by IP, for example when a customer’s firewall only lets approved addresses through. The IPs of an Application Load Balancer change, so we always address it by its DNS name.

For routing it is the other way round. The ALB reads host and path of a request on layer 7 and can send shop.example.com and api.example.com to different target groups. The NLB only sees IP address, port and protocol on layer 4. According to the docs its listeners can spread traffic across several target groups by weight, and on a dual-stack NLB rules can separate IPv4 from IPv6. It cannot route by host or path. Even with a TLS listener it only uses SNI to pick the right certificate, it cannot distribute by domain.

The load balancer only distributes the load across existing instances. How many there are is decided by the Auto Scaling group (ASG). We set a minimum, a desired and a maximum number. The ASG replaces unhealthy instances, starts new ones when needed and registers them with the load balancer. This is the elasticity from Part 01 in technical form.

A load balancer distributes traffic to instances of an Auto Scaling group in AZ a and AZ b. A CloudWatch alarm at CPU above 70 percent adds a new instance that is registered with the load balancer. Minimum 2, desired 3, maximum 6

Scaling strategyTrigger
Manualwe change the desired number by hand
Simple / step scalinga CloudWatch alarm crosses a threshold
Target trackinga target value is maintained, such as CPU at 40 %
Scheduledknown patterns, such as more capacity every Monday at 9 a.m.
Predictiveforecast by machine learning from past load

Lambda computes only when something happens

With EC2 we pay for an instance as long as it runs, whether it is working at the moment or not. AWS Lambda turns that around. We only upload code, and AWS runs it as soon as an event arrives. Servers, patches and scaling are AWS’s job. This is called serverless, even though servers are of course still running, just not ours.

The typical example is image processing after an upload.

Uploading photo.jpg to the uploads bucket triggers an ObjectCreated event. Lambda creates a thumbnail in the thumbnails bucket and writes name, size and date to DynamoDB. Billing is by invocations and duration times memory

Lambda has hard limits. An execution may last at most 15 minutes, and memory goes up to 10,240 MB (Lambda quotas, as of October 25, 2026). Billing is per invocation and by duration times allocated memory, measured in GB-seconds. 1 million invocations and 400,000 GB-seconds per month are permanently free according to AWS, in the Free Plan and the Paid Plan alike. Lambda allocates CPU power in proportion to the configured memory, so more memory also means more compute (AWS Knowledge Center).

Anyone who needs an API for a Lambda function puts Amazon API Gateway in front of it. It provides serverless REST, HTTP and WebSocket APIs and is the usual front door for Lambda backends. For a scheduled job, a cron replacement, Amazon EventBridge triggers the function on a schedule instead.

Containers with ECS, Fargate and EKS

Between your own instance and the function lie containers. A Docker image bundles an application and its dependencies and runs the same everywhere. AWS offers several services for this, with similar names and clearly separated jobs.

ServiceMemory aid
Amazon ECSorchestrate Docker containers, in EC2 mode on instances that we provision ourselves
AWS Fargaterun containers serverless, no EC2 instances to manage
Amazon EKSmanaged Kubernetes, on EC2 or Fargate
Amazon ECRprivate registry for Docker images
AWS Batchbatch jobs as a Docker image, on EC2, Spot or Fargate, even if they run longer than Lambda allows
Amazon Lightsailsimple virtual servers and ready-made stacks at a predictable flat price, without automatic scaling

The most common mix-up concerns ECS and Fargate. ECS is the orchestrator, Fargate is a mode of operation in which AWS provides the underlying servers. Kubernetes in the question almost always leads to EKS. Lightsail is the answer when someone with no cloud experience wants a simple web server quickly, with predictable costs.

Hands-on

We create a small Python function, invoke it twice and read the billing from the logs. The function needs an IAM role so that Lambda may write to CloudWatch Logs. How roles and temporary credentials work is explained in Part 02. We use the CLI because, unlike clicks in the console, commands can be repeated. The Exam Guide asks about this distinction between a one-off operation and a repeatable process (Task 3.1).

The code in index.py (the German test strings “Welt” and “Hallo” mean “world” and “hello”):

def handler(event, context):
    name = event.get('name', 'Welt')
    print('Aufruf fuer', name)
    return {'message': f'Hallo {name}', 'memory_mb': context.memory_limit_in_mb, 'remaining_ms': context.get_remaining_time_in_millis()}

memory_mb is returned as a string, and remaining_ms is the remaining time until the timeout in milliseconds.

The trust policy trust.json allows the Lambda service to assume the role.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "lambda.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}

Create the role, package the code, create the function:

aws iam create-role --role-name ccp-demo-lambda-role \
  --assume-role-policy-document file://trust.json
aws iam attach-role-policy --role-name ccp-demo-lambda-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

zip fn.zip index.py

# The role ARN contains our own account ID, so we look it up
ROLE_ARN=$(aws iam get-role --role-name ccp-demo-lambda-role \
  --query Role.Arn --output text)

aws lambda create-function --function-name ccp-demo-hello \
  --runtime python3.13 --architectures arm64 \
  --memory-size 128 --timeout 10 \
  --handler index.handler \
  --role "$ROLE_ARN" \
  --zip-file fileb://fn.zip \
  --region eu-central-1

In the console: Lambda → Event Functions → Create Event Function → Author from scratch → Function name, Runtime → Additional settings → ARM64 architecture → Create Event Function. Python 3.13 is listed in the Runtime dropdown under “Other supported”. The console creates the execution role itself (ccp-demo-hello-role-… with its own policy AWSLambdaBasicExecutionRole-…), so trust.json and the two iam commands are not needed there. We then enter the code in the Code tab and click Deploy. In the console the file is called lambda_function.py and the handler lambda_function.lambda_handler, so the function in the code is lambda_handler instead of handler.

“Create Event Function” form with “Author from scratch”, Function name ccp-demo-hello and Runtime Python 3.13. Under Permissions the note that Lambda creates an execution role with permissions for CloudWatch Logs by default. Under Additional settings “ARM64 architecture” is switched on, “Custom execution role” off

Now we invoke the function:

aws lambda invoke --function-name ccp-demo-hello \
  --cli-binary-format raw-in-base64-out \
  --payload '{"name":"rotecodefraktion"}' \
  response.json --region eu-central-1
cat response.json
{
    "StatusCode": 200
}
{"message": "Hallo rotecodefraktion", "memory_mb": "128", "remaining_ms": 10000}

The output is shortened, as the CLI also reports the executed version. A second invocation with {"name":"CLF-C02"} also returned status 200. Measured at the client, the first invocation took 725 ms and the second 539 ms. More interesting is what Lambda itself logs and bills.

aws logs filter-log-events \
  --log-group-name /aws/lambda/ccp-demo-hello \
  --filter-pattern "?INIT_START ?REPORT" \
  --query 'events[].message' --output text --region eu-central-1
INIT_START Runtime Version: python:3.13.mainlinev2.v43 ...
REPORT ... Duration: 2.03 ms  Billed Duration: 68 ms  Memory Size: 128 MB  Max Memory Used: 35 MB  Init Duration: 65.38 ms
REPORT ... Duration: 1.62 ms  Billed Duration: 2 ms ...

The output is shortened, and we leave out request IDs and further fields.

In the console: Test tab → Create new event → Event name, Event JSON → Test. Under “Executing function: succeeded” and Details we find Response, Duration, Billed duration, Init duration and the last 4 KB of the Log output; the “logs” link leads to the CloudWatch log group.

Result of a test run in the console: “Executing function: succeeded”, Response with the greeting, Duration 1.80 ms, Billed duration 64 ms and Init duration 61.75 ms, below it the Log output

The screenshot comes from a second run, also a cold start, hence the slightly different times.

The first invocation was a cold start. Lambda first had to spin up an execution environment and load the Python runtime, as the INIT_START line and the init duration of 65.38 ms show. The actual code ran for only 2.03 ms. Still, 68 ms were billed, so init phase and runtime together.

Since August 1, 2025, according to the AWS Compute Blog, AWS also bills the init phase for ZIP functions with managed runtimes.

On the second invocation the environment was still warm, there was no init phase, and 2 ms were billed. At 128 MB this doesn’t matter within the Free Tier. For functions with a lot of memory and many cold starts, the init phase becomes a line item on the bill.

Clean up so that nothing is left behind:

aws lambda delete-function --function-name ccp-demo-hello --region eu-central-1
aws logs delete-log-group --log-group-name /aws/lambda/ccp-demo-hello --region eu-central-1
aws iam detach-role-policy --role-name ccp-demo-lambda-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
aws iam delete-role --role-name ccp-demo-lambda-role

If we created the function in the console, we delete the automatically created role ccp-demo-hello-role-… and its policy AWSLambdaBasicExecutionRole-… instead of ccp-demo-lambda-role (IAM → Roles and IAM → Policies).

At this scale, the function stays within the free tier. Resources that we leave running longer or invoke more often can incur costs once the Free Tier expires or is exceeded.

For the exam

Keyword in the questionAnswer
short-term, unpredictable load, no commitmentOn-Demand
steady load over 1 or 3 years, fixed instance typeStandard Reserved Instance or EC2 Instance Savings Plan
discount that also covers Fargate and LambdaCompute Savings Plan
fault-tolerant, may be interrupted, cheapest possibleSpot Instances
license per socket or core, compliance requires own serverDedicated Host
hardware not shared with other customers, no visibility into sockets and coresDedicated Instance
manage bring-your-own licenses (BYOL) and track their useAWS License Manager
preconfigured image from a third-party vendorAMI from the AWS Marketplace
Who applies guest OS patches and maintains security group rules on an EC2 instance?the customer
Who replaces faulty server hardware under EC2?AWS
capacity guaranteed in an AZ, no term commitmentCapacity Reservation
routing by path or host (domain), HTTP/HTTPSApplication Load Balancer
static IP address, e.g. for a customer’s firewall allowlistNetwork Load Balancer (or Global Accelerator in front of an ALB)
TCP/UDP, extreme performanceNetwork Load Balancer
integrate third-party firewall appliancesGateway Load Balancer
adjust the number of instances to load automaticallyAuto Scaling group
code without servers, event-driven, under 15 minutesAWS Lambda
serverless REST or WebSocket API in front of LambdaAmazon API Gateway
many batch jobs as a Docker image, longer than 15 minutesAWS Batch
containers without EC2 managementAWS Fargate
KubernetesAmazon EKS
private Docker registryAmazon ECR
simple web server at a flat priceAmazon Lightsail
connection runs into a timeoutcheck the security group

Typical traps:

  • Savings Plans don’t reserve capacity. Guaranteed capacity comes only with a Capacity Reservation.
  • Only the NLB has static IP addresses, only the ALB routes by domain. Both are reachable by DNS name.
  • The Classic Load Balancer is not shut down. What was shut down in 2022 was EC2-Classic.
  • Spot is never the answer for databases or critical jobs, even though it is the cheapest option.
  • Lambda ends after 15 minutes. Longer jobs belong to AWS Batch, Fargate or EC2.
  • Lambda doesn’t run just any Docker image. A container image for Lambda needs a runtime interface client that talks to the Lambda service, and it must sit in an Amazon ECR repository in the same Region. Anyone who wants to run an existing image unchanged ends up with ECS or Fargate.
  • ECS is not automatically serverless. Only with Fargate does the management of instances go away.

Sources

The next part is about storage, from EBS and EFS to the S3 storage classes.