9.3
Shared Storage and Launching Fast
EBS vs EFS for an app tier, golden AMIs, user data and restoring from snapshots.
18 min Reading + animations
Tip: tap or hover any dotted-underlined term to see what it means.
By the end of this lesson you will be able to
- Explain why a WordPress-style application is stateful in its files (uploads) as well as in its database and sessions, and why that breaks when you add servers.
- Say why an EBS volume cannot be the shared uploads folder of a web fleet (one AZ, one instance, Multi-Attach is not a shared file system), and how EFS solves it with mount targets in every AZ.
- Choose between EBS, EFS and S3 (with CloudFront) for user uploads, with the cost of each.
- Move the database from RDS Multi-AZ to Aurora MySQL with readers, and say what each step buys.
- Cut the time it takes a new instance to become useful: golden AMI, user data, the hybrid of both, warm pools, and data restored from RDS and EBS snapshots without the first-read penalty.
- Draw the typical 3-tier web architecture and follow a request, a write and an AZ failure through every tier.
#A blog that stores files, not only rows
#Three kinds of state
Lesson 9.1 grew a stateless app: any server could answer any request. Lesson 9.2 had a shop whose state was a session (the shopping cart) and rows in a database, and moved both off the web servers into ElastiCache and RDS. This lesson’s app has a third kind of state: files.
Think of a blogging platform built on WordPress, the most common content management system (CMS) on the web. We will call it Kolom.example (“kolom” is Bengali for pen). It has to:
- scale out and in freely behind a load balancer, across several Availability Zones;
- store posts, comments and users in a MySQL database;
- let authors upload pictures, and show them correctly to every reader.
WordPress keeps the first two in MySQL, but uploaded images (and installed themes and plugins) are ordinary files in a folder on the server’s disk, wp-content/uploads. That folder is state too. If two servers have two different folders, they show two different websites.
| Kind of state | Example in Kolom | Where it must live to scale | Lesson |
|---|---|---|---|
| Session | Who is logged in | ElastiCache or DynamoDB, not server memory | 9.2, 7.5 |
| Rows | Posts, comments, users | A database: RDS or Aurora | 7.1–7.3 |
| Files | Uploaded photos, themes, plugins | Shared storage: EFS (or S3) | this lesson, 5.4 |
The lesson tells the story in two parts. First the architecture: the database tier, then the file problem and its fix. Then a toolbox for a different question that every scaling design runs into: how quickly can a new instance actually serve traffic?
#The database tier: from RDS Multi-AZ to Aurora
The first version of Kolom uses RDS for MySQL with Multi-AZ: a primary in one AZ and a synchronous standby in another (lesson 7.1). That gives high availability: if the primary fails, RDS fails over to the standby in about one to two minutes and the endpoint follows.
It does not give read scaling. A blog is read far more often than it is written, perhaps a hundred page views per comment. A Multi-AZ standby (the classic single-standby deployment) serves no traffic at all, so all the reads land on the primary. When a post goes viral, the primary’s CPU climbs and every page slows down while the standby sits idle.
The next step is Amazon Aurora MySQL (lesson 7.3):
- It is MySQL-compatible, so WordPress connects to it without code changes.
- Up to 15 Aurora Replicas (readers) share one storage volume that keeps six copies across three AZs. Replica lag is usually milliseconds, because readers do not replay a copy of the data; they read the same storage.
- The cluster endpoint always points at the writer; the reader endpoint spreads connections over the readers. Replica auto scaling can add readers when their CPU rises.
- If the writer fails, Aurora promotes a reader, typically in under 30 seconds, and moves the cluster endpoint.
So “Multi-AZ and read replicas, with the least effort” is Aurora’s strength. Plain RDS can do it too, with read replicas that each have their own endpoint, or a Multi-AZ DB cluster with two readable standbys; Aurora packages it most neatly. A cache in front (ElastiCache, lesson 7.5) removes even more reads; you will see it in the 3-tier picture at the end.
The blog’s database: from RDS Multi-AZ to Aurora
Posts, comments and users live in MySQL. Both web servers talk to the database tier below them; watch what happens when reads grow and when the database fails.
Scenario
The first database: RDS for MySQL with Multi-AZ. A primary in AZ a, and a synchronous standby in AZ b that serves no traffic at all (lesson 7.1).
#Stage 1: one server, uploads on its EBS volume
With one web server, the simplest place for uploads is the server’s own disk: an EBS volume. An author uploads a photo, the server writes it into wp-content/uploads, and later every reader’s request reaches the same server, which reads the same disk. It works, it is cheap, and for a single-instance application it is the right answer.
Remember what EBS is (lesson 5.1): a network disk that lives in one Availability Zone and is attached to one instance. Those two facts do not matter while there is one instance. They are the whole problem as soon as there are two.
#Stage 2: two servers, and the photo vanishes
Kolom gets popular, and an Auto Scaling group now runs instances in two AZs behind an Application Load Balancer. Each instance was launched from the same AMI and got its own EBS volume.
- An author uploads
sunset.jpg. The load balancer sends that request to web-a, which saves the file on its volume in AZ a. - A reader opens the post. The load balancer sends this request to web-b, which looks in its uploads folder.
- The file is not there. The reader sees a broken image. Depending on which server each request reaches, half the readers see the photo and half do not.
Where do uploaded images live?
A blog on EC2 behind a load balancer. Each post can have photos that users upload. Follow one photo: saved by one server, requested later through another.
Scenario
The first version: one instance with its uploads folder on its own EBS volume.
The blog starts small: one instance in one AZ. Posts and users live in a MySQL database (next animation); the uploaded photos are files in a folder on the instance’s EBS volume.
#Why the volume cannot simply be shared
- One AZ. An EBS volume can only be attached to instances in its own Availability Zone. web-b in AZ b cannot attach a volume in AZ a at all.
- One instance. A normal volume attaches to one instance at a time.
- Multi-Attach is not a shared folder. EBS Multi-Attach lets one io1 or io2 (Provisioned IOPS) volume attach to up to 16 Nitro instances in the same AZ. But ordinary file systems such as ext4 and XFS are not designed for several servers writing at once; Multi-Attach needs a cluster-aware file system or an application that coordinates writes itself. It cannot cross AZs and cannot be a boot volume. It is for clustered databases and similar software, not for a WordPress fleet.
#Workarounds that only look like fixes
- Sticky sessions (lesson 6.4) keep one user on one server. Here the uploader and the readers are different users, so they still land on different servers. And when scale-in terminates web-a, its volume, with the photos, can be deleted with it.
- Copying files between servers with a cron job or a sync tool: always a little behind, breaks quietly, and every new instance starts empty.
- Your own NFS server on one EC2 instance: now that instance, its disk and its AZ are a single point of failure, and you patch and scale it yourself.
What the fleet needs is one file system that every instance, in every AZ, can mount at the same time.
#Stage 3: EFS, one file system for every AZ
Amazon EFS (lesson 5.4) is a managed NFS file system. Move wp-content/uploads (or the whole wp-content folder) onto it and every server sees the same files:
- Regional. A Regional file system stores data redundantly in at least three AZs, and instances in any AZ of the Region can mount it at the same time.
- Mount targets. The file system reaches your VPC through one mount target per AZ: an ENI with a private IP in a subnet of that AZ. Each instance mounts the file system’s DNS name, which resolves to the mount target in its own AZ, so traffic stays local and avoids cross-AZ charges.
- Security groups on the mount targets. Each mount target has a security group that must allow inbound TCP 2049 (NFS) from the web servers’ security group. A missing rule does not give a clear error: the mount hangs and times out.
- Pay per GB used. No size to provision; it grows and shrinks with the files. EFS Standard costs about $0.30 per GB-month in us-east-1, almost four times gp3’s $0.08, but you pay only for what is stored, once, instead of a full-size volume per instance. Lifecycle management moves old, unread files to Infrequent Access or Archive for much less.
- Linux only, POSIX permissions, many thousands of clients. For a Windows fleet the answer is FSx for Windows File Server.
New instances mount EFS at boot, from user data or an /etc/fstab entry, and see every file at once. Scaling out, scaling in and losing an AZ no longer lose a single photo.
#EBS, EFS or S3 for uploaded files?
EFS is the answer the slides and the exam give for this architecture, because it needs no change to the application: WordPress still writes to a folder. Modern designs often go one step further and keep uploads in Amazon S3, served through Amazon CloudFront, AWS’s content delivery network. S3 and CloudFront each get their own chapters later in the course; here is the comparison you need now:
| EBS | EFS | S3 + CloudFront | |
|---|---|---|---|
| What it is | Block disk for one instance | Shared NFS file system | Object storage + CDN |
| Shared by many instances | No (Multi-Attach: same AZ, io1/io2, cluster-aware only) | Yes, thousands, across AZs | Yes, through the S3 API or a URL |
| Scope | One AZ | Region (Regional type) | Region (S3), edge locations worldwide (CloudFront) |
| App change needed | None | None: it is a folder | Yes: upload through the S3 API (WordPress uses an offload plugin) |
| Price per GB-month (us-east-1) | gp3 $0.08, provisioned, per instance | Standard $0.30, used | S3 Standard about $0.023, used (plus requests and transfer) |
| Who serves the image | The web server | The web server | CloudFront, without touching the web tier |
| Best for | One instance, databases, boot disks | Shared files a legacy app writes as files | Large media libraries, global readers |
A worked example: Kolom has 120 GB of photos and runs four instances.
- EBS: each instance needs its own copy on, say, a 200 GB gp3 volume: 4 × 200 × $0.08 = $64 per month, and the copies still are not shared.
- EFS Standard: 120 × $0.30 = $36 per month, one shared copy. With lifecycle management moving old photos to IA, much less.
- S3 Standard: 120 × $0.023 ≈ $2.76 per month for storage, plus requests and data transfer; with CloudFront the web servers stop serving images altogether.
Self-checkQuestion
A WordPress site runs on six EC2 instances in an Auto Scaling group across three AZs. Users report that newly uploaded images appear only sometimes. The team wants a fix that needs no change to the WordPress code. What should they do?
#The WordPress journey in one view
| Stage | Design | Problem it leaves |
|---|---|---|
| 1 | One instance, MySQL on RDS, uploads on the instance’s EBS volume | No scaling, one AZ |
| 2 | Auto Scaling group across AZs, each instance with its own EBS | Uploads visible only on the server that received them |
| 3 | Uploads on EFS, mounted in every AZ through mount targets | Database reads concentrate on one primary |
| 4 | Aurora MySQL: writer + readers across AZs, reader endpoint | (Optional) images still served by web servers → S3 + CloudFront later |
Summing up the slides’ lesson: EBS for single-instance data, EFS for data that a distributed application shares, Aurora for easy Multi-AZ and read replicas.
#Launching fast: where the minutes go
The second half of this lesson is a toolbox. Every design in this chapter depends on Auto Scaling adding instances when load rises (lesson 6.5). An instance added during a spike only helps once it serves traffic, and everything it does before that is time when users get slow pages or errors. Launching a full stack (EC2, EBS, RDS) can take a long time because of four kinds of work:
- Installing the operating system packages, runtime, application and agents.
- Inserting data: the initial data set, or the data to recover from.
- Configuring everything for this environment: endpoints, file systems, feature flags, secrets.
- Starting the application and passing health checks.
The cloud lets you do most of that work once, ahead of time, and reuse the result. For EC2 that means a golden AMI and a small user data script; for data, it means restoring from snapshots.
#Golden AMI: bake the slow part once
A golden AMI is your own image with everything that is slow and the same everywhere already installed: OS patches, web server, PHP, the application code, plugins, the monitoring and security agents (lesson 4.3). Instances launched from it skip the install step entirely.
| Benefit | Why it matters during a scale-out |
|---|---|
| Fast boot | Ready in a minute or two instead of many minutes |
| Consistency | Every instance is byte-for-byte the same; no “package version drifted on the third server” |
| No dependency at launch | Nothing to download, so a package mirror outage or a private subnet without a NAT gateway does not stop scaling |
| Tested once | The image is tested before it is used; a bad build never reaches the fleet |
The price is a process. A golden AMI is a snapshot in time and it goes stale: when a security patch or a new application version comes out, you rebuild the AMI, test it, point the launch template at the new version and replace the instances (an instance refresh). You do not patch the running servers by hand. EC2 Image Builder automates this pipeline: a recipe (base image plus build and test components), a schedule or a trigger when the base image changes, and distribution to other Regions and accounts. Remember that an AMI belongs to one Region; copy it to every Region you launch in.
Bake, then bootstrap
A golden AMI carries everything that is slow and the same everywhere. User data adds only what differs per environment. Follow one image from the pipeline to a serving instance.
Scenario
The pipeline starts a temporary build instance from a base image (here Amazon Linux 2023) and runs the slow steps once: OS patches, web server, PHP, the blog code and plugins, the agents.
#User data: only what differs per launch
User data is the script cloud-init runs once, at the first boot, as root (lesson 4.3). It is the right place for dynamic configuration, things a single AMI cannot know in advance:
- which environment this is (dev, staging, production) and therefore which database endpoint, which EFS file system, which cache;
- fetching settings from Systems Manager Parameter Store and secrets from Secrets Manager, using the instance’s IAM role, never writing passwords into the user data itself;
- mounting EFS, registering with monitoring, joining a cluster.
User data is a poor place for the heavy work. A script that runs dnf update and installs a whole stack makes every instance spend minutes before it serves, depends on the internet at every launch, and can fail halfway while the instance still passes its EC2 status checks. Keep it short; the raw limit is 16 KB anyway.
#The hybrid: golden AMI plus a small user data script
The usual answer is both:
- bake the slow, unchanging parts into a golden AMI;
- bootstrap the per-environment parts with a short user data script.
One AMI then serves every environment, and each instance is ready in about the time it takes to boot. AWS Elastic Beanstalk works exactly this way: its platforms are AMIs with the runtime pre-installed, and at launch it adds your application version and configuration (you will see Beanstalk in lesson 9.4).
| Approach | Boot time | Per-environment config | Weak point |
|---|---|---|---|
| Plain AMI + big user data | Slow (many minutes) | Easy | Slow scale-out, depends on the internet, drift |
| Golden AMI only | Fastest | Needs one AMI per environment, or config baked in | Many images to keep patched |
| Golden AMI + small user data | Fast | Easy | Needs an image pipeline (Image Builder) |
#Side note: warm pools
When even a golden AMI is not fast enough (for example an application that loads gigabytes into memory or onto disk when it starts), an Auto Scaling group can keep a warm pool: instances launched and initialised ahead of time, then kept Stopped (cheapest: you pay only for their EBS volumes and Elastic IPs), Hibernated (memory saved to the EBS root volume) or Running (expensive, rarely worth it). On scale-out the group starts a pool instance instead of launching a new one.
- By default the pool size is maximum capacity − desired capacity; you can set your own maximum prepared capacity and a minimum pool size.
- Use a lifecycle hook so an instance is not stopped before its first initialisation has finished.
- Starting a stopped instance is not a first boot, so user data does not run again unless you configure it to run on every boot.
- Limits: no Spot Instances and no instance weighting in a mixed instances group with a warm pool; the root device must be EBS.
On the exam, “instances take too long to be ready” is answered by a golden AMI first; a warm pool is the answer when the question stresses an exceptionally long initialisation that cannot be baked away.
#Try the launch strategies
Traffic jumps from 150 to 540 requests per second; two instances can serve 200. At 2:00 the group launches four more. Change how the instances are built, add a warm pool, restore a data volume from a snapshot, or break the package repository, and see how many requests fail before the new capacity arrives:
Launch speed during a traffic spike
Traffic jumps at 1:00 and the Auto Scaling group launches four more instances at 2:00. Choose how the instances are built, then press play and count the failed requests while they get ready.
How the instance is built
Warm pool
Data volume
Package repository
Time
0:00
Demand (req/s)
150
Healthy capacity (req/s)
200
Failed requests so far
0
All 6 at full speed
not yet
What happened
Nothing yet. Press play.
Two instances serve 150 requests per second. Press play: at 1:00 the demand jumps to 540 per second, and every request above the healthy capacity fails.
With this model’s timings (illustrative, not measured), the four new instances reach full speed this long after launch:
| Build | Time to full speed | Failed requests in 15 minutes |
|---|---|---|
| Plain AMI + 8 min of installs in user data | 9 min 45 s | about 219,000 |
| Golden AMI + small user data | 2 min 15 s | about 66,000 |
| Golden AMI | 1 min 45 s | about 56,000 |
| Warm pool (any build) | 1 min 15 s | about 46,000 |
| Plain AMI, repository down | never | about 291,000 |
The gap between the first two rows is pure arithmetic: 8 extra minutes × 340 missing requests per second = 163,200 more failed requests, all because the install happens at launch instead of before.
#Data that is ready: restoring from snapshots
The same idea applies to data. Instead of building a database or a disk and then loading data into it, start from a snapshot that already holds it.
#RDS: restore the database from a snapshot
Restoring an RDS snapshot gives you a database whose schemas and data are already in place: no installing MySQL, no importing a dump, which for a big database can take hours. Use it to create a staging copy with real data, to recover after a mistake, or to start a new environment. Remember from lesson 7.2:
- A restore always creates a new DB instance with a new endpoint. Point the application at it with a Route 53 CNAME you own (for example
db.staging.example.com) or a value in Parameter Store, and no server changes. - The restored instance gets the default parameter and option groups unless you name others; check the security group too.
- Its storage is lazy loaded from S3, so the first queries are slower until the data has been read once. Warm it up before you measure.
#EBS: restore a volume from a snapshot
A volume created from an EBS snapshot is already formatted and full of data: attach it, mount it, use it. (Every AMI does this for its root volume.) But it is lazy loaded too: the volume is available in seconds, and each block is fetched from S3 the first time it is read, so first reads are slow (lesson 5.1). For a server that must be fast immediately:
| Option | What it does | Cost |
|---|---|---|
| Do nothing | Blocks arrive on first read and in the background | Free, but slow and unpredictable at first |
| Initialise the volume | Read every block once with fio or dd before real traffic | Free, takes minutes to hours |
| Provisioned rate for volume initialisation | Set 100 to 300 MiB/s when creating the volume; it is fully initialised in a predictable time | Per GiB of snapshot data |
| Fast Snapshot Restore (FSR) | Enabled per snapshot per AZ; volumes are fully initialised at creation | About $0.75 per snapshot per AZ per hour (us-east-1) |
A 60 GiB snapshot at a provisioned rate of 300 MiB/s is fully initialised in about 61,440 ÷ 300 ≈ 205 seconds, under four minutes. FSR is faster still, but it is billed for every hour it is enabled, in every AZ, used or not, and limited by volume creation credits (lesson 5.1). If you set a provisioned rate on a snapshot that has FSR enabled, the rate wins.
A new environment from snapshots
A staging copy of the blog for tomorrow’s test, with real data. Instead of installing MySQL and importing a dump, restore the database and the data volume from snapshots.
Scenario
You restore last night’s RDS snapshot. Schema, tables, users and data are all inside it: nothing to install, nothing to import.
#The typical 3-tier web application
Put the pieces of this chapter together and you get the architecture that appears again and again on the exam:
| Tier | Subnets | Services | What it does |
|---|---|---|---|
| Entry | Global | Route 53 | Alias record for the domain → the load balancer |
| Presentation | Public subnets in each AZ | ELB (an ALB) | Ends TLS, health-checks and spreads requests |
| Application | Private subnets in each AZ | EC2 in an Auto Scaling group, from a golden AMI | Runs the app; keeps no state of its own |
| Data | Data (private) subnets in each AZ | ElastiCache (sessions and cached data), RDS/Aurora (read/write data, replicas, Multi-AZ) | Holds the state |
| Storage | Per AZ / Region | EBS per instance, EFS shared | Boot disks; shared files |
- Every tier exists in at least two AZs, so one AZ can fail without taking the site down.
- Security groups chain tier to tier: the ALB allows 443 from the internet, the web servers allow traffic only from the ALB’s security group, the cache and the database only from the web servers’ group (lesson 9.2).
- The application tier is stateless: sessions in ElastiCache, rows in Aurora, files in EFS. That is what makes it safe to add and remove instances freely, and the golden AMI is what makes adding them fast.
The typical 3-tier web application
Route 53 points at the load balancer in public subnets; web servers in an Auto Scaling group in private subnets; ElastiCache and Aurora in data subnets. Follow a request through every tier.
Scenario
The user’s browser asks for www.example.com. Route 53 answers from an alias record that points at the load balancer.
#What goes wrong
- Uploads on the instance disk in a fleet. Images appear and disappear depending on the server; scale-in deletes them. Move them to EFS (or S3).
- EFS mount fails in one AZ. No mount target in that AZ, or its security group lacks inbound TCP 2049 from the web servers; a NACL blocking 2049 or the return ports. The symptom is a timeout, not an error message.
- App starts without its mount. The web server writes into the empty local folder under the mount point, and the old bug returns on that one server. Mount at boot with
_netdevin/etc/fstaband make the health check fail if the mount is missing. - Reads overload the database while a Multi-AZ standby idles. Add readers (Aurora) and a cache.
- Stale golden AMI. New instances are born without the latest patches. Rebuild on a schedule with Image Builder and roll out with an instance refresh.
- Big user data at boot. Slow scale-out, version drift, and a launch that fails whenever the repository is unreachable, while EC2 status checks still look fine.
- Secrets in user data. Readable from the instance and through the API. Use Secrets Manager or Parameter Store with the instance role.
- Restored data is slow. Lazy loading on restored EBS volumes and RDS storage. Use FSR, a provisioned initialisation rate, or warm it up.
- Restored database, old endpoint. The application still points at the old instance. Use a CNAME or a parameter, not a hard-coded endpoint.
#Shared storage and fast launch in system design
- Make the web tier disposable. If killing any instance loses nothing (sessions, rows and files all live elsewhere), Auto Scaling, Spot Instances, AZ failures and deployments all become routine.
- Pick storage by who shares it: EBS for one instance, EFS for a fleet that needs a file system, S3 for objects read by many, especially from many places.
- Bake, then bootstrap. Golden AMIs from a pipeline, user data for environment settings, configuration in Parameter Store, secrets in Secrets Manager.
- Measure time to useful, not time to “running”: boot, user data, app start, health checks, cache and disk warm-up. That number decides how much spare capacity you must keep, and how aggressive scaling has to be.
- Restore instead of rebuild for data: snapshots for staging copies and recovery, with FSR or initialisation when performance matters on the first minute.
#Try it yourself
The commands use made-up IDs; replace them with your own.
# 1. EFS for the uploads folder: a file system and one mount target per AZ
aws efs create-file-system --performance-mode generalPurpose --throughput-mode elastic \
--encrypted --tags Key=Name,Value=myblog-uploads
aws efs create-mount-target --file-system-id fs-0abc1234 \
--subnet-id subnet-0aaa1111 --security-groups sg-0efs0001 # AZ a
aws efs create-mount-target --file-system-id fs-0abc1234 \
--subnet-id subnet-0bbb2222 --security-groups sg-0efs0001 # AZ b
# The mount targets' security group: NFS only from the web servers' security group
aws ec2 authorize-security-group-ingress --group-id sg-0efs0001 \
--protocol tcp --port 2049 --source-group sg-0web0001
# 2. Small user data for the hybrid approach (the AMI already has httpd, PHP and the app)
cat > user-data.sh <<'EOF'
#!/bin/bash
set -euo pipefail
ENV=prod
DB=$(aws ssm get-parameter --name /$ENV/blog/db-endpoint --query Parameter.Value --output text)
FS=$(aws ssm get-parameter --name /$ENV/blog/efs-id --query Parameter.Value --output text)
echo "$FS:/ /var/www/html/wp-content/uploads efs _netdev,tls 0 0" >> /etc/fstab
mount -a
sed -i "s/DB_HOST_PLACEHOLDER/$DB/" /var/www/html/wp-config.php
systemctl enable --now httpd
EOF
# 3. Bake: create an AMI from a configured instance, or run an Image Builder pipeline
aws ec2 create-image --instance-id i-0123456789abcdef0 --name blog-v12
aws imagebuilder start-image-pipeline-execution \
--image-pipeline-arn arn:aws:imagebuilder:us-east-1:111122223333:image-pipeline/blog
# 4. A warm pool of stopped instances for the Auto Scaling group
aws autoscaling put-warm-pool --auto-scaling-group-name blog-asg \
--pool-state Stopped --min-size 2
# 5. Data that is ready: a database and a volume from snapshots
aws rds restore-db-instance-from-db-snapshot --db-instance-identifier blog-staging \
--db-snapshot-identifier blog-prod-2026-10-24 --db-subnet-group-name blog-data
aws ec2 create-volume --snapshot-id snap-0123456789abcdef0 \
--availability-zone us-east-1a --volume-type gp3 --volume-initialization-rate 300
aws ec2 enable-fast-snapshot-restores --availability-zones us-east-1a \
--source-snapshot-ids snap-0123456789abcdef0
On a running instance, check the mount and the boot log:
df -h /var/www/html/wp-content/uploads # should show the EFS file system, not the root disk
sudo tail -n 50 /var/log/cloud-init-output.log
#Summary
Key takeaways
- A WordPress-style app has three kinds of state: sessions, rows and files (uploads). All three must leave the web servers before the web tier can scale freely.
- Database: RDS Multi-AZ gives availability but its standby serves no reads; Aurora MySQL adds up to 15 readers on shared six-copy storage, a reader endpoint and failover in under 30 seconds.
- EBS is one AZ and normally one instance: fine for a single-instance app, wrong as a fleet’s shared folder. Multi-Attach is io1/io2, same AZ, up to 16 Nitro instances, cluster-aware software only.
- EFS is Regional NFS: one mount target (ENI) per AZ, security group allowing TCP 2049 from the instances, mounted by every instance, pay per GB used, Linux only. The exam answer for shared WordPress uploads.
- For uploads at scale, S3 + CloudFront is the modern design (later chapters); EFS needs no application change.
- Launching fast: golden AMI for the slow, unchanging parts (rebuild and roll out with Image Builder and instance refresh); user data for per-environment config, once at first boot; the hybrid of both is the usual answer and how Beanstalk works. Warm pools keep pre-initialised stopped instances for very long initialisations.
- Data that is ready: RDS restore from snapshot (schemas and data in place; new instance, new endpoint) and EBS restore from snapshot (formatted, with data); both are lazy loaded, fixed by FSR, a provisioned initialisation rate or reading every block once.
- The 3-tier web app: Route 53 → ALB in public subnets → Auto Scaling group in private subnets → ElastiCache and RDS/Aurora in data subnets, EBS/EFS for storage, every tier in at least two AZs, security groups chained tier to tier.
Answer on your own first, then read the explanation, even when you got it right.
Self-checkQuestion
In a WordPress site, which piece of state is stored as ordinary files on the web server’s disk by default?
Self-checkQuestion
Why does an RDS for MySQL Multi-AZ DB instance not help when a blog’s database CPU is overloaded by reads?
Self-checkQuestion
A blog moves from RDS for MySQL to Aurora MySQL. Which two statements about the result are true?
Choose 2
Self-checkQuestion
An Aurora MySQL cluster has a writer in AZ a and one reader in AZ b. The writer’s host fails. What happens?
Self-checkQuestion
A single EC2 instance runs a small internal wiki and stores its attachments on its EBS volume. There is no plan to add instances. Is that a reasonable design?
Self-checkQuestion
Two web servers in two AZs each have their own EBS volume. An image uploaded through server A returns 404 when the request reaches server B. What is the root cause?
Self-checkQuestion
An engineer proposes attaching the uploads EBS volume in AZ a to the web servers in AZ a and AZ b with Multi-Attach. Which two facts make this a bad plan?
Choose 2
Self-checkQuestion
A team turns on load balancer stickiness so that users keep seeing the images they upload. Why does that not fix the missing-image problem?
Self-checkQuestion
How do EC2 instances in three AZs reach one Regional EFS file system?
Self-checkQuestion
New web servers in AZ c hang for a minute when mounting EFS, then fail with Connection timed out. Servers in AZ a and AZ b mount fine. What is the most likely cause?
Self-checkQuestion
Which two statements about EFS for a WordPress fleet are true?
Choose 2
Self-checkQuestion
Kolom has 120 GB of uploaded images. Option 1: four instances each with a 200 GB gp3 volume holding a copy ($0.08 per GB-month). Option 2: one EFS Standard file system ($0.30 per GB-month). What are the monthly storage costs?
Self-checkQuestion
A news site serves millions of image views a day to readers worldwide. The team is willing to change how the application uploads files. Which design scales best and keeps image traffic off the web servers?
Self-checkQuestion
Which statement best summarises when to use EBS and when to use EFS?
Self-checkQuestion
An Auto Scaling group takes 12 minutes to bring a new instance into service because user data installs a web server, a runtime and the application. Scale-out during spikes is too slow. What is the best fix?
Self-checkQuestion
The same application runs in dev, staging and production, each with its own database endpoint and file system. The team wants fast launches and one image to maintain. Which approach fits?
Self-checkQuestion
Which two are typical jobs for user data in a golden AMI design?
Choose 2
Self-checkQuestion
An administrator edits the user data of an Auto Scaling group’s launch template, but the existing instances do not change. Why?
Self-checkQuestion
A company launches instances from a golden AMI built six months ago. A security audit finds that new instances are missing critical patches. What should the company do?
Self-checkQuestion
During a scale-out, demand is 540 requests per second and the healthy capacity is 200 until the new instances are ready. Design A makes them ready 9 min 45 s after launch, design B after 1 min 45 s. How many more requests fail with design A?
Self-checkQuestion
An application takes 20 minutes to load reference data into memory and onto disk when it starts, even from a golden AMI. Spikes must be absorbed within a couple of minutes. What should the architect add?
Self-checkQuestion
An Auto Scaling group has desired capacity 6 and maximum capacity 10. A warm pool is created with default settings. How many instances does it prepare?
Self-checkQuestion
Which two statements about warm pools are true?
Choose 2
Self-checkQuestion
A team needs a staging database with last night’s production data within 30 minutes. Production is RDS for MySQL with automated backups and nightly snapshots. What is the fastest correct approach?
Self-checkQuestion
An instance is launched with a 500 GiB data volume created from a snapshot. The first hour after launch shows very high read latency, then performance becomes normal. What explains it?
Self-checkQuestion
A volume is created from a snapshot holding 60 GiB of data with a provisioned initialisation rate of 300 MiB/s. About how long until it is fully initialised?
Self-checkQuestion
Volumes restored from one snapshot must give full performance from the first second, in two AZs, during a planned migration weekend. What should the team use, and what should they remember about cost?
Self-checkQuestion
In the typical 3-tier web architecture, where do the EC2 web servers usually run?
Self-checkQuestion
A 3-tier app runs in two AZs. Users must stay logged in even if any one web server or one AZ fails. Where should the sessions be stored?
Self-checkQuestion
In a 3-tier app, AZ a fails, taking a web server, the ElastiCache primary and the Aurora writer with it. What must the team change in Route 53 to keep the site reachable?