Design High-Performing and Elastic Compute Solutions for AWS SAA-C03

If you’ve spent any time studying for SAA-C03, you’ve probably noticed the exam is rarely asking, “Which AWS compute service is the coolest?” It’s asking, “What workload pattern is this, what is the real bottleneck, and which service is the best fit?” That is exactly how good architecture works in production too.

For this domain, keep a few distinctions straight. Scalability is the ability to handle more work. Elasticity is the ability to scale up and down with changing demand. High availability means reducing downtime through resilient design, usually across multiple Availability Zones. Fault tolerance is a stronger concept and implies continued operation through failures with minimal impact, though exam wording is sometimes less strict than formal engineering usage. And cost-performance efficiency means choosing the least operationally painful and most economical option that still meets performance goals.

How I’d think about choosing the right compute model

Start with the workload first, not the AWS service name. I usually walk through these questions in order:

  • So, is this workload talking to users directly, chugging along in the background, or only waking up when an event comes in?
  • Does it actually need to run all the time, or can it just spin up when something kicks it off?
  • Does the job finish within 15 minutes, or are we dealing with one of those longer-running tasks that needs a different design? If yes, Lambda stays in play.
  • Do you need OS-level access, custom agents, or specialized host tuning? If yes, think EC2.
  • Is the app containerized? If yes, think ECS. If you want serverless containers, think ECS with Fargate. If Kubernetes is explicitly required, think EKS.
  • Is the workload interruption-tolerant? If yes, Spot may be part of the answer.
  • Is startup latency critical? If yes, warm pools, provisioned concurrency, or pre-warmed container capacity may matter.
Best fit Use when Avoid when
Amazon EC2 is the one I reach for when I need a real VM with full operating system control. It’s the best fit when you need OS-level control, you’re lifting and shifting something older, you need special hardware, or the workload runs pretty steadily for long stretches. You want minimal ops and the app fits serverless or managed containers
AWS Lambda Event-driven, short-lived, stateless processing, bursty APIs, automation Long-running jobs, persistent host state, heavy runtime control requirements
Amazon ECS Container orchestration without Kubernetes complexity You need Kubernetes APIs or ecosystem features specifically
AWS Fargate Serverless compute for ECS or EKS containers with low ops You need deep host control or the lowest possible steady-state node cost
Amazon EKS Kubernetes is a hard requirement Kubernetes is optional and ECS would solve it more simply
Elastic Beanstalk is the managed option I think of for straightforward web apps when you don’t want to hand-build the plumbing. It’s a managed deployment layer for standard web apps that still uses EC2 underneath, but takes care of the load balancing and Auto Scaling pieces for you. You’d skip it when you need really fine-grained infrastructure control or you’re better off with modern container orchestration.
AWS Batch Queued batch jobs, array jobs, asynchronous compute pipelines Interactive applications
Lightsail Simple VPS-style workloads and small sites Advanced VPC-native elastic architectures

EC2 performance tuning essentials

EC2 is still the broadest compute option because you can control the instance type, storage, networking, startup behavior, and how you buy capacity. That flexibility is great, honestly, but it also means bad sizing decisions tend to bite you pretty quickly.

Match instance family to the dominant bottleneck. General purpose fits balanced workloads. Compute optimized fits CPU-bound services. Memory optimized fits caches and memory-heavy databases. Storage optimized fits very high local I/O. Accelerated computing fits GPUs and specialized inference or HPC tasks.

Two exam-relevant details are commonly missed. First, burstable T-family instances are cost-effective for low-to-moderate baseline CPU workloads, but sustained CPU-heavy use can exhaust CPU credits and hurt performance. They’re great for dev and test, small web apps, and workloads that only spike now and then, but they’re definitely not the best fit for something that needs heavy CPU all day long. Second, Graviton instances often deliver better price-performance than comparable x86 families when your software supports ARM. If the scenario is pushing cost optimization and there’s no hard dependency on x86, Graviton is usually a very strong candidate.

Modern instance sizing is not just vCPU and memory. Network bandwidth and EBS bandwidth scale with instance type too. Many “slow compute” problems are really storage or network ceilings. I’d use CloudWatch, app telemetry, and load testing to figure out whether the real problem is CPU, memory, I/O, or just waiting on something downstream.

Storage and network performance interactions

Compute decisions are often wrong because storage design was ignored. For EBS, know the major volume patterns. gp3 is the common general-purpose SSD choice and lets you provision IOPS and throughput independently from size. gp2 still appears in legacy environments, but gp3 is usually the better modern answer. io1/io2 are for high-performance, latency-sensitive workloads that need provisioned IOPS; io2 is the more durable premium option. st1 is throughput-optimized HDD for large sequential workloads, while sc1 is cold HDD for infrequently accessed data, not performance-sensitive applications.

Instance store is ephemeral local storage attached to the host. It does not persist through stop, hibernate, terminate, or host failure, though a reboot does not erase it. Use it for scratch space, caches, and temporary high-speed data. Use EBS for persistent block storage. If multiple instances need shared file access, the answer may be EFS rather than bigger EC2.

Many modern EC2 types are EBS-optimized by default, so the exam is more likely to test the concept of storage throughput than a manual toggle. On the network side, ENA enhanced networking improves throughput and lowers latency. If a question mentions low-latency east-west traffic, high packet rates, or tightly coupled nodes, also think about placement groups. Cluster placement groups are usually single-AZ, and they’re a good fit when you need very low latency and high throughput between instances. Partition placement groups improve fault isolation for distributed systems. Spread placement groups reduce correlated failure for small numbers of critical instances, but they do not scale infinitely.

Now let’s talk about elasticity with Auto Scaling and load balancing, because this is where a lot of real-world designs either click or fall apart.

For a resilient web or app tier, the pattern I usually want is an Auto Scaling group spread across multiple subnets and multiple Availability Zones, with a load balancer sitting in front of it. That’s a best practice, sure, but it doesn’t happen by magic; you’ve actually got to build for it. Auto Scaling takes care of baseline capacity, scale-out and scale-in events, and replacing unhealthy instances when things go sideways.

Target tracking is usually the best default scaling policy. Step scaling is useful when you want larger reactions to larger breaches. Scheduled scaling fits known traffic windows. Predictive scaling can scale ahead of recurring patterns. Simple scaling still exists, but target tracking and step scaling are generally preferred.

Scale on meaningful metrics. CPU is common, but not always correct. For web tiers, request count per target is often better. For workers, queue depth is usually better. EC2 memory utilization is not published to CloudWatch by default; you need the CloudWatch agent or custom metrics.

Health behavior matters. ASGs can use EC2 health checks and load balancer health checks. A health check grace period prevents premature replacement while instances boot. Estimated instance warmup helps scaling policies avoid reacting before new capacity is really ready. Warm pools reduce scale-out delay, but they do not eliminate application initialization work. Lifecycle hooks let you pause launch or termination for bootstrap, registration, or cleanup. Termination policies, instance protection, and deregistration delay help avoid killing the wrong nodes during scale-in.

For cost optimization, use mixed instances and Spot carefully. Spot is a great option for stateless or retryable workloads, especially if you diversify the instance types and use capacity-optimized or price-capacity-optimized allocation strategies. If the workload can’t tolerate interruptions, I’d keep Spot out of the critical path or use it only as extra overflow capacity. Capacity rebalance and interruption handling are important guardrails.

With load balancers, know the selector cold. ALB is Layer 7 for HTTP and HTTPS and supports host-based, path-based, header, method, query-string, and source-IP rule matching. That’s exactly why it’s such a strong fit for web apps, APIs, gRPC services, and microservices. NLB is Layer 4 for TCP, UDP, and TLS, supports static IP addresses, preserves source IP, and can terminate TLS with TLS listeners, but it does not do Layer 7 routing. ALB passes client IP in headers such as the standard forwarded-for header. GWLB is for virtual network appliances using appliance insertion, not generic application balancing.

Also know target types and draining behavior. ALB can target instances, IPs, and Lambda in supported patterns. Cross-zone load balancing, health checks, idle timeouts, and deregistration delay all affect real performance and graceful scale-in.

Lambda operational design patterns

Lambda is excellent for event-driven elasticity, but only when the workload actually fits that model cleanly. Key facts: maximum execution time is 15 minutes per invocation, functions are stateless, concurrency is governed by quotas, and scaling behavior depends on the trigger type.

For synchronous triggers like API Gateway, latency and concurrency are the two things you really want to keep an eye on. For asynchronous triggers like S3 or EventBridge, retries and failure handling become much more important. For SQS event source mappings, Lambda polls the queue and scales consumers based on queue traffic, batch settings, and concurrency limits, so the behavior differs from direct request-driven invocation.

Reserved concurrency sets a hard cap and reserves capacity for a function. Provisioned concurrency pre-initializes execution environments on versions or aliases to reduce cold starts. Memory tuning affects not only memory but also CPU and, in practice, other performance characteristics such as network throughput. Lambda also supports configurable ephemeral storage in temporary local function storage, which matters for temporary file processing.

For exam questions, don’t forget to think about retries, dead-letter queues or destinations, and idempotency. If the same event could arrive more than once, your function needs to handle duplicates without falling apart. If a Lambda function needs to reach VPC resources, putting it inside a VPC adds some extra design considerations and quota limits, including ENI-related scaling constraints.

Now, containers. ECS, Fargate, and EKS each solve a different part of the container problem, so it’s really important not to mix them up.

The most important correction here is conceptual: ECS is the orchestrator. Fargate is a serverless compute engine for ECS and EKS, not a competing orchestrator.

In ECS, the main pieces are the cluster, the task definition, and the service. Task definitions hold the practical stuff: CPU, memory, container image, ports, logging, and IAM. The task execution role is used by ECS to pull images and publish logs. The task role is what the application container uses to call AWS APIs. Amazon ECR is the common image registry in AWS-native designs.

ECS with EC2 gives more control and can be more cost-efficient for steady, dense workloads. ECS with Fargate reduces node management and is often the best answer when the prompt says “no servers to manage.” ECS also supports capacity providers, which are useful for balancing EC2 and Fargate strategies or mixing On-Demand and Spot capacity.

EKS is the right answer when the question explicitly says Kubernetes is required. AWS manages the EKS control plane, but you still have to think about worker nodes, managed node groups or Fargate profiles, plus the usual concerns around ingress, networking, observability, and scaling. That extra operational overhead is exactly why EKS is usually the wrong choice when Kubernetes isn’t actually required. At a high level, pod scaling and node scaling are separate concerns, commonly handled with Kubernetes autoscaling components and dynamic node provisioning tools.

Specialized options

Elastic Beanstalk is the managed option I think of for straightforward web apps when you don’t want to hand-build the plumbing. is a managed deployment layer for standard web applications. It sets up and coordinates the underlying pieces like EC2, Auto Scaling, and Elastic Load Balancing for you. AWS Batch is for queued batch workloads and can use EC2 or Fargate compute environments depending on job needs and cost goals. Lightsail is for simple VPS-style use cases and is usually not the answer for advanced elastic enterprise architectures.

When the best answer is decoupling, not bigger compute

A lot of performance problems are solved by architecture, not brute force. If the web tier slows down under bursts, buffering with SQS may be better than scaling synchronously. If multiple systems need the same event, EventBridge or SNS fan-out may be cleaner than adding more app servers. If repeated reads are expensive, caching may beat bigger instances. On the exam, “millions of small events,” “burst absorption,” and “asynchronous processing” are strong clues that decoupling is part of the solution.

Troubleshooting compute architectures is usually where the real learning happens.

I usually start with the symptom first, because that keeps me from going down the wrong rabbit hole. High latency with low CPU often means storage, network, lock contention, or a slow downstream dependency. ALB unhealthy targets usually point to bad health check paths, security group mistakes, app startup delays, or the wrong port. ASG launches instances but traffic still fails often means bootstrap took too long, the instance never became healthy, or deregistration and warmup settings are wrong. Lambda throttling points to concurrency limits or downstream bottlenecks. ECS task placement failures often mean insufficient CPU, memory, ENIs, subnet IPs, or capacity provider issues. Batch jobs stuck in queue usually means compute environment capacity or configuration problems.

Use CloudWatch for metrics and alarms, distributed tracing tools for request-path latency, and Systems Manager for fleet diagnostics and patching. Use CloudTrail for audit and change analysis, not direct performance telemetry. If performance changed suddenly, CloudTrail helps answer, “What changed?”

Security for elastic compute

Security is part of good compute design. For EC2, use IAM roles instead of static credentials, enforce IMDSv2, prefer SSM Session Manager over open SSH or RDP where possible, encrypt EBS with KMS, and patch through Systems Manager. For load-balanced tiers, I’d use security-group-to-security-group references so the targets only accept traffic from the load balancer, which is a clean and practical control. For Lambda and containers, stick with least-privilege IAM, and keep secrets in a proper secrets manager rather than hardcoding them anywhere.s Manager or Parameter Store, and scan container images in ECR. The shared responsibility model shifts a bit depending on the service: with EC2, you’re responsible for the guest OS and hardening; with Lambda and Fargate, AWS takes on more of the infrastructure, but you still own IAM, code, data, and configuration security.

Cost-performance and purchasing choices

For EC2, On-Demand fits unpredictable usage. Savings Plans are often the most flexible commitment answer; know that Compute Savings Plans are broader, while EC2 Instance Savings Plans are narrower. Reserved Instances still matter, but Standard and Convertible Reserved Instances differ in flexibility. Dedicated Instances provide single-tenant instance placement. Dedicated Hosts provide host-level visibility and control, which is what you want for some bring-your-own-license and compliance scenarios.

For serverless economics, Lambda is excellent for intermittent and bursty workloads, but at high sustained utilization containers or EC2 may become more cost-effective. Fargate trades some cost efficiency for operational simplicity. The exam often rewards that trade-off when “low operational overhead” is a stated requirement.

Exam patterns, traps, and rapid review

  • Must use Kubernetes → EKS
  • No servers to manage → Lambda or ECS with Fargate
  • Need host OS access → EC2
  • Static IP and high-performance TCP or UDP → NLB
  • Path-based or host-based HTTP routing → ALB
  • Event-driven, short-lived, under 15 minutes → Lambda
  • Fault-tolerant batch → AWS Batch or Spot-backed workers
  • Bring-your-own-license or host-level licensing → Dedicated Host
  • Shared file system across instances → likely EFS, not just larger EC2
  • Stateful app sessions on web tier → externalize state rather than relying on sticky sessions

Final 30-second checklist: identify the workload pattern, find the real bottleneck, choose the compute model, choose the scaling model, then eliminate answers that violate runtime limits, operational constraints, or resilience requirements. That is how you get the right answer on SAA-C03 and in production.