Pair your devices with a code and playback position follows you: pause on this device, hit resume on the other. Position is saved to the site every minute and on pause.
Open this panel on your other device and enter the same code.
The point of this lab is a habit, not a skill. Every number in this module came from a page I fetched on a particular day. Several I could not retrieve and flagged as unverified. The habit worth building is checking a claim against the live system before you rely on it — in an exam, in a design review, or in a support case.
So this lab is short, cheap, and consists almost entirely of proving FAQ sentences true in your own account.
You will need: the AWS CLI v2 configured, and jq. No RDS instance and no EC2 instance are
created, deliberately — those cost money and the facts we need are observable without them.
export LAB=saa0-$(date +%Y%m%d)-$RANDOM
export REGION=$(aws configure get region)
echo "LAB=$LAB REGION=$REGION"
Lesson 4 claims AWS reserves five IP addresses per subnet, so a /28 gives 11 usable rather than 14. Prove it.
VPC=$(aws ec2 create-vpc --cidr-block 10.99.0.0/16 \
--query Vpc.VpcId --output text)
aws ec2 create-tags --resources $VPC --tags Key=Name,Value=$LAB
AZ1=$(aws ec2 describe-availability-zones \
--query 'AvailabilityZones[0].ZoneName' --output text)
SUB=$(aws ec2 create-subnet --vpc-id $VPC --cidr-block 10.99.1.0/28 \
--availability-zone $AZ1 --query Subnet.SubnetId --output text)
aws ec2 describe-subnets --subnet-ids $SUB \
--query 'Subnets[0].{Cidr:CidrBlock,AZ:AvailabilityZone,Available:AvailableIpAddressCount}'
Q1. What is AvailableIpAddressCount? A /28 has 16 addresses. Record the number, subtract, and
state how many AWS reserved. Quote the FAQ sentence.
Q2. Before running the next command, predict the answer: what will AvailableIpAddressCount be
for a /24?
SUB24=$(aws ec2 create-subnet --vpc-id $VPC --cidr-block 10.99.2.0/24 \
--availability-zone $AZ1 --query Subnet.SubnetId --output text)
aws ec2 describe-subnets --subnet-ids $SUB24 \
--query 'Subnets[0].AvailableIpAddressCount'
Record whether your prediction was right.
Q3. Now test the CIDR size constraint. Try to create a /29 subnet and a /12 VPC:
aws ec2 create-subnet --vpc-id $VPC --cidr-block 10.99.3.0/29 \
--availability-zone $AZ1 2>&1 | tail -2
aws ec2 create-vpc --cidr-block 10.98.0.0/12 2>&1 | tail -2
Paste both errors. Which FAQ sentence do they confirm, and what are the two boundary values?
Lesson 4's most load-bearing claim: "A subnet must reside within a single Availability Zone."
# Every AZ in your Region
aws ec2 describe-availability-zones \
--query 'AvailabilityZones[].{Name:ZoneName,Id:ZoneId,State:State}' --output table
# The VPC you created — which AZ is it in?
aws ec2 describe-vpcs --vpc-ids $VPC \
--query 'Vpcs[0].{Id:VpcId,Cidr:CidrBlock}'
Q4. The subnet output in Q1 had an AvailabilityZone field. Does the VPC output have one? What
does that tell you about the scope of each resource? Write the one-sentence version you'd say in an
interview.
Q5. You need an Auto Scaling group spread across every AZ in this Region. Using the count from the table above, how many subnets must you create, and why can't you do it with one?
Q6. There is no CLI command to make a subnet span two AZs. Explain in one sentence why the absence of a command is stronger evidence than a documentation sentence would be on its own.
We won't create three VPCs and peer them — instead, read the authoritative statement of the constraint from the API's own behaviour and documentation.
# Confirm the constraint's consequence in the route table model:
# a peering route must name a specific pcx, so there is no "via B" route to C.
aws ec2 describe-route-tables \
--filters Name=vpc-id,Values=$VPC \
--query 'RouteTables[0].Routes'
Q7. The route table has one route. What is its target, and what is its scope? Now reason about it: if you added a peering route for VPC B's CIDR, what would you have to add to reach VPC C, and what does the FAQ say about that?
Q8. Do the arithmetic that sells Transit Gateway. For n VPCs that all need to reach each other,
peering needs n(n-1)/2 connections. Fill in the table:
| n VPCs | Peering connections needed |
|---|---|
| 3 | |
| 5 | |
| 10 | |
| 20 |
Q9. Write the two-sentence recommendation you would give a team that currently has 4 peered VPCs and is about to add 6 more. Cite the FAQ.
BUCKET=$LAB-verify
aws s3api create-bucket --bucket $BUCKET --region $REGION \
$( [ "$REGION" = "us-east-1" ] || echo "--create-bucket-configuration LocationConstraint=$REGION" )
# Claim: minimum object size is 0 bytes
: > /tmp/$LAB-empty
aws s3api put-object --bucket $BUCKET --key empty.txt --body /tmp/$LAB-empty
aws s3api head-object --bucket $BUCKET --key empty.txt \
--query '{Size:ContentLength,Encryption:ServerSideEncryption}'
Q10. Record both fields. Which two separate claims did that one command just verify — one from lesson 3, one from SAA1 lesson 5?
Q11. Strong read-after-write consistency. Write an object, immediately overwrite it, immediately read it:
echo "v1" | aws s3 cp - s3://$BUCKET/consistency.txt
echo "v2" | aws s3 cp - s3://$BUCKET/consistency.txt
aws s3 cp s3://$BUCKET/consistency.txt -
What did you get, and what would older study material have predicted? Quote the FAQ sentence.
Q12. The honest limit of this test. You ran it once and got v2. Explain in two sentences why
a single successful read does not prove strong consistency, and what the actual basis for the claim
is. (This one matters more than the command did.)
QURL=$(aws sqs create-queue --queue-name $LAB-q --query QueueUrl --output text)
aws sqs get-queue-attributes --queue-url $QURL \
--attribute-names MessageRetentionPeriod VisibilityTimeout \
ReceiveMessageWaitTimeSeconds MaximumMessageSize \
--query Attributes
Q13. Record all four values in seconds and convert them to human units. Which one matches the FAQ's stated default retention? Which two were flagged as unverified in lesson 5, and what are the real values in your account?
Q14. Now demonstrate the visibility-timeout bug from lesson 5 without writing a consumer:
aws sqs set-queue-attributes --queue-url $QURL \
--attributes VisibilityTimeout=5
aws sqs send-message --queue-url $QURL --message-body "process me" >/dev/null
# receive it, but do NOT delete it — simulating a slow consumer
aws sqs receive-message --queue-url $QURL --query 'Messages[0].MessageId' --output text
# immediately again — should be empty, the message is invisible
aws sqs receive-message --queue-url $QURL --query 'Messages' --output text
Wait for the visibility timeout to expire, then receive again:
aws sqs receive-message --queue-url $QURL --wait-time-seconds 10 \
--query 'Messages[0].MessageId' --output text
Q15. Is the second MessageId the same as the first? Explain what just happened in terms of
at-least-once delivery, and state the design rule that follows.
Q16. The --wait-time-seconds 10 in that last command is long polling. What is
ReceiveMessageWaitTimeSeconds set to on the queue by default (from Q13), and what does that mean
about which polling mode you get if you don't ask?
Q17. Try to set a retention period outside the documented range:
aws sqs set-queue-attributes --queue-url $QURL \
--attributes MessageRetentionPeriod=1500000 2>&1 | tail -2
Paste the error. What are the enforced boundaries, and do they match the FAQ's "1 minute to 14 days"?
Lesson 3, 4 and 5 flagged facts I could not retrieve. This part is the actual homework.
Q18. Pick three of the following, look them up in the AWS documentation, and write down the value and the URL you got it from:
Q19. For one of the three, state what you would have answered from memory before looking it up, and whether you'd have been right. Be honest — this is the whole point of the exercise.
aws sqs delete-queue --queue-url $QURL
aws s3 rm s3://$BUCKET --recursive
aws s3api delete-bucket --bucket $BUCKET
aws ec2 delete-subnet --subnet-id $SUB
aws ec2 delete-subnet --subnet-id $SUB24
aws ec2 delete-vpc --vpc-id $VPC
rm -f /tmp/$LAB-*
Verify it, don't assume it — which is, after all, the lab's entire thesis:
aws ec2 describe-vpcs --vpc-ids $VPC 2>&1 | tail -1 # expect an error
aws s3api list-buckets --query "Buckets[?starts_with(Name,'$LAB')].Name"
aws sqs list-queues --queue-name-prefix $LAB
head-object call.