Skip to content
AWS Certified Solutions Architect - Associate (SAA-C03)

High-Performing Storage, Compute, and Databases

Last verified against its sources on 23 September 2026

Domain 3 of the SAA-C03 exam — Design High-Performing Architectures — is worth 24% of your score and covers five task statements across storage, compute, databases, networking, and data ingestion. This module covers the first three: choosing storage (EBS volume types, EFS, FSx) and compute (EC2 instance families, containers, Lambda) for a workload's dominant performance constraint, and choosing a database (Aurora, RDS, DynamoDB) and caching strategy to match its access pattern and scale. Expect scenarios that name the specific bottleneck — IOPS, latency, throughput, access pattern — and ask which AWS service removes it.

Choosing High-Performing Storage

  • Choose the right EBS volume type for a given IOPS or throughput requirement.
  • Choose between Amazon EBS, Amazon EFS, and Amazon FSx for a given file-sharing or performance requirement.

AWS storage splits into three types, and picking the wrong one is one of the most common exam traps. Object storage (Amazon S3) stores whole files with metadata, accessed over HTTP, with no fixed limit on total capacity. Block storage (Amazon EBS) presents raw, low-level volumes that an operating system formats and mounts like a local disk — the natural fit for a database's data files. File storage (Amazon EFS, Amazon FSx) presents a shared file system that many instances can mount at once, complete with a directory structure.

An EBS volume lives in one Availability Zone and attaches to one instance at a time (a few volume types support Multi-Attach to several instances in the same AZ, but that's the exception, not the default). Within EBS, gp3 is the default general-purpose SSD: every volume gets a 3,000 IOPS and 125 MiB/s baseline free, and you can provision more independently of size. io2 is the provisioned-IOPS SSD for the most demanding, latency-sensitive transactional workloads — the highest IOPS ceiling EBS offers. st1 (throughput-optimized HDD) and sc1 (cold HDD) are priced for large, sequential, throughput-heavy workloads like log processing, not for high IOPS.

bash

aws ec2 create-volume \
  --availability-zone us-east-1a \
  --volume-type gp3 \
  --size 500 \
  --iops 6000 \
  --throughput 500
Create a gp3 volume with IOPS and throughput provisioned above the free baseline.

When several instances need to read and write the same files at once — a shared content repository, a home directory for a fleet of application servers — a block volume won't do, because only one instance can mount it at a time. Amazon EFS is a managed, POSIX-compliant file system that many instances (and Lambda functions) can mount concurrently across multiple Availability Zones. Its General Purpose performance mode is the default and gives the lowest per-operation latency; Max I/O is a legacy mode that trades higher latency for a higher ceiling on aggregate throughput and IOPS, and AWS recommends General Purpose for nearly every workload today. EFS's throughput can scale with Bursting (tied to file system size), Provisioned (a fixed rate you set), or Elastic (scales automatically with actual usage).

Amazon FSx offers purpose-built file systems for specific ecosystems: FSx for Windows File Server for SMB-based Windows workloads, and FSx for Lustre for high-performance computing workloads — like machine learning training — that need very high, parallel throughput straight from S3 data.

A quick decision framework: if the workload is a database's data files or a boot volume, and only one instance needs it, reach for EBS, and pick the volume type by the dominant performance need — IOPS for io2, throughput for st1, cost for sc1, and gp3 for nearly everything else. If several instances or functions need concurrent read/write access to the same files, reach for EFS. If the workload is Windows-native file sharing or high-performance computing with a Lustre-aware toolchain, reach for the matching FSx file system. And if what you're really storing is discrete objects — images, backups, log files, data lake files — none of the above is right: that's S3.

An application needs a shared directory that 12 EC2 instances across two Availability Zones can all read and write to at once. Would an EBS volume work?Answer it yourself first, then open this.

No — an EBS volume attaches to (at most) one instance at a time in one AZ. This needs a file system like Amazon EFS, built for concurrent multi-instance, multi-AZ access.

Elastic and High-Performing Compute

  • Select an EC2 instance family for a given workload's dominant resource constraint.
  • Size an AWS Lambda function's memory setting for a CPU-bound task.

Amazon EC2 groups instance types into families by which resource they're built to maximize, and matching the family to a workload's dominant constraint is the first performance decision to make. General purpose instances (like the M family) balance compute, memory, and networking for workloads with no single standout need — web servers, small-to-medium databases. Compute optimized instances (the C family) favor CPU over memory, suited to batch processing, media transcoding, and other CPU-bound work. Memory optimized instances (the R and X families) favor RAM over CPU, built for in-memory databases and large-dataset analytics. Storage optimized instances (the I and D families) deliver very high, low-latency local disk I/O for workloads like high-throughput databases and data processing. Accelerated computing instances add GPUs or other hardware accelerators for machine learning training and graphics-heavy workloads.

Picking the family is a matter of naming the bottleneck: if a workload is CPU-bound, more memory on a general-purpose instance won't help nearly as much as moving to a compute-optimized one.

bash

aws ec2 run-instances \
  --image-id ami-0abcdef1234567890 \
  --instance-type c7g.2xlarge \
  --count 1
Launch a compute-optimized instance for a CPU-bound batch job.

For workloads packaged as containers, the next decision is who manages the servers underneath them. Running containers on Amazon ECS or Amazon EKS with EC2 gives you full control over the instance type (and therefore the family) the containers run on — useful when a container workload has the same kind of dominant resource need as any other EC2-hosted workload. AWS Fargate runs those same containers without you provisioning or managing any EC2 instances at all: you specify the CPU and memory the task needs, and Fargate handles the rest, trading some control over the underlying hardware for less operational overhead.

The same tradeoff shows up outside containers. AWS Lambda takes it furthest: no server or container to size at all, only a memory setting for the function, and a request-scoped runtime with a hard duration limit — the right fit for short, event-driven work rather than a long-running service.

Inside AWS Lambda, memory is the one dial that changes almost everything else: Lambda allocates CPU power in proportion to the memory you configure, so a memory-bound, CPU-bound, or network-bound function can often get faster simply by turning the memory setting up, with no code change. At 1,769 MB, a function has the equivalent of one full vCPU; below that, it shares a fraction of a vCPU.

Because Lambda bills for memory and duration together, more memory doesn't automatically cost more — if doubling the memory more than halves the run time, the total bill can actually drop. Guessing the right setting is unreliable; AWS's open-source Lambda Power Tuning tool runs a function at several memory levels and measures the real cost/ performance curve, which is the reliable way to pick a setting instead of assuming "more memory always costs more."

A Lambda function's average duration is 800ms at 512 MB memory. You double the memory to 1024 MB and duration drops to 350ms. Does the bill go up or down?Answer it yourself first, then open this.

It can go down — Lambda bills for memory times duration together, and more than halving the duration while only doubling the memory reduces the total, even though the per-millisecond price at 1024 MB is higher.

High-Performing Database Solutions

  • Choose between Amazon Aurora, Amazon RDS, and Amazon DynamoDB for a given workload's data model and scale.
  • Choose a DynamoDB capacity mode and caching strategy for a given traffic pattern.

Choosing a database starts with the data model and the scale. Amazon RDS runs a familiar relational engine (MySQL, PostgreSQL, and others) as a managed service. Amazon Aurora is AWS's own MySQL- and PostgreSQL-compatible relational engine, built on a distributed storage layer replicated across three Availability Zones independently of compute — which is what lets an Aurora cluster support up to 15 low-lag read replicas. Amazon DynamoDB is a fully managed key-value and document database with single-digit-millisecond latency at any scale, for workloads that fit a simpler access pattern (fetch or write by key) rather than complex multi-table joins.

The dominant signal for which one fits: if the workload needs joins, transactions across many tables, or ad hoc queries, a relational engine (RDS or Aurora) is the natural fit. If the access pattern is predictable — look up an item by a known key, at very high and unpredictable scale — DynamoDB usually performs better and scales with less operational effort.

bash

aws dynamodb update-table \
  --table-name Orders \
  --billing-mode PAY_PER_REQUEST
Switch a DynamoDB table to on-demand capacity mode.

DynamoDB tables choose between two capacity modes. On-demand is serverless: DynamoDB scales instantly to any previously reached traffic level, bills per request, and needs no capacity planning — the default and recommended starting point, especially for unpredictable or spiky traffic. Provisioned capacity has you set read and write capacity units ahead of time; it costs less at a steady, predictable load, but under-provisioning it means requests get throttled.

Encryption ties back to a choice you already know from securing data: every DynamoDB table is encrypted at rest, using either an AWS owned key, an AWS managed key, or a customer managed KMS key — the same customer-managed-vs-AWS-managed tradeoff that applies to any AWS KMS key. A finance table with an auditor-mandated rotation schedule needs a customer managed key for exactly the same reason a finance dataset in general does: only a customer managed key lets you set your own rotation and deletion schedule.

When a hot set of read queries repeatedly hits the same rows — a product catalog, a leaderboard — Amazon ElastiCache can absorb that load in memory in front of RDS, Aurora, or DynamoDB. Lazy loading (cache-aside) only loads data into the cache when it's actually requested: check the cache first, and on a miss, read from the database and write the result into the cache for next time. It tolerates a completely empty cache node gracefully — every request just falls through to the database — but data can go stale until it's requested again. Write-through updates the cache every time the application writes to the database, so cached data is never stale, at the cost of writing data to the cache that might never be read, and failing outright if the cache node it's writing to is unavailable.

A cache node used for write-through caching goes down for 10 minutes. What happens to writes to the database during that window?Answer it yourself first, then open this.

They can fail outright, because write-through tries to update the cache on every write — unlike lazy loading, which only touches the cache on reads and keeps working with a downed or empty cache node.

Sources